Skip to content

Commit 20f3120

Browse files
ijjkhuozhi
andauthored
[next-server] preserve rsc query for rsc redirects (#78876)
Backport of #77963 to 15.3.x Co-authored-by: Jiachi Liu <[email protected]>
1 parent b464d18 commit 20f3120

File tree

8 files changed

+131
-3
lines changed

8 files changed

+131
-3
lines changed

packages/next/src/shared/lib/router/utils/prepare-destination.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
INTERCEPTION_ROUTE_MARKERS,
1212
isInterceptionRouteAppPath,
1313
} from './interception-routes'
14-
import { NEXT_RSC_UNION_QUERY } from '../../../../client/components/app-router-headers'
1514
import { getCookieParser } from '../../../../server/api-utils/get-cookie-parser'
1615
import type { Params } from '../../../../server/request/params'
1716

@@ -210,8 +209,6 @@ export function prepareDestination(args: {
210209
query: NextParsedUrlQuery
211210
}) {
212211
const query = Object.assign({}, args.query)
213-
delete query[NEXT_RSC_UNION_QUERY]
214-
215212
const parsedDestination = parseDestination(args)
216213

217214
const { hostname: destHostname, query: destQuery } = parsedDestination
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { ReactNode } from 'react'
2+
export default function Root({ children }: { children: ReactNode }) {
3+
return (
4+
<html>
5+
<body>{children}</body>
6+
</html>
7+
)
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Page() {
2+
return (
3+
<div>
4+
<h1>Redirect Dest</h1>
5+
</div>
6+
)
7+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Link from 'next/link'
2+
3+
export default function Home() {
4+
return (
5+
<div>
6+
{/* disable prefetch to align the dev/prod fetching behavior,
7+
it's easier for writing tests */}
8+
Go to{' '}
9+
<Link prefetch={false} href="/redirect/source">
10+
Redirect Link
11+
</Link>
12+
</div>
13+
)
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Page() {
2+
return (
3+
<div>
4+
<h1>Rewrite Dest</h1>
5+
</div>
6+
)
7+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Link from 'next/link'
2+
3+
export default function Home() {
4+
return (
5+
<div>
6+
{/* disable prefetch to align the dev/prod fetching behavior,
7+
it's easier for writing tests */}
8+
Go to{' '}
9+
<Link prefetch={false} href="/rewrite/source">
10+
Rewrite Link
11+
</Link>
12+
</div>
13+
)
14+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @type {import('next').NextConfig}
3+
*/
4+
const nextConfig = {
5+
reactStrictMode: true,
6+
async redirects() {
7+
return [
8+
{
9+
source: '/redirect/source',
10+
destination: '/redirect/dest',
11+
permanent: true,
12+
},
13+
]
14+
},
15+
async rewrites() {
16+
return [
17+
{
18+
source: '/rewrite/source',
19+
destination: '/rewrite/dest',
20+
},
21+
]
22+
},
23+
}
24+
25+
module.exports = nextConfig
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { nextTestSetup } from 'e2e-utils'
2+
import { retry } from 'next-test-utils'
3+
import { Request } from 'playwright'
4+
5+
describe('rsc-query-routing', () => {
6+
const { next } = nextTestSetup({
7+
files: __dirname,
8+
})
9+
10+
it('should contain rsc query in rsc request when redirect the page', async () => {
11+
const browser = await next.browser('/redirect')
12+
13+
const rscRequestUrls: string[] = []
14+
browser.on('request', (req: Request) => {
15+
if (req.url().includes('?_rsc=')) {
16+
rscRequestUrls.push(req.url())
17+
}
18+
})
19+
20+
// Click redirect link
21+
const link = await browser.elementByCss('a')
22+
await link.click()
23+
24+
// Wait for the page load to be completed
25+
await retry(async () => {
26+
expect(await browser.elementByCss('h1').text()).toBe('Redirect Dest')
27+
})
28+
29+
// The redirect source and dest urls should both contain the rsc query
30+
expect(rscRequestUrls[0]).toContain('/redirect/source')
31+
expect(rscRequestUrls[1]).toContain('/redirect/dest')
32+
})
33+
34+
it('should contain rsc query in rsc request when rewrite the page', async () => {
35+
const browser = await next.browser('/rewrite')
36+
37+
const rscRequestUrls: string[] = []
38+
browser.on('request', (req: Request) => {
39+
if (req.url().includes('?_rsc=')) {
40+
rscRequestUrls.push(req.url())
41+
}
42+
})
43+
44+
// Click redirect link
45+
const link = await browser.elementByCss('a')
46+
await link.click()
47+
48+
// Wait for the page load to be completed
49+
await retry(async () => {
50+
expect(await browser.elementByCss('h1').text()).toBe('Rewrite Dest')
51+
})
52+
53+
// The rewrite source url should contain the rsc query
54+
expect(rscRequestUrls[0]).toContain('/rewrite/source')
55+
})
56+
})

0 commit comments

Comments
 (0)