Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 17a1202

Browse files
authored
test: add some test cases ensuring next.config redirects/rewrites don't result in cache poisoning (#2879)
1 parent 695eced commit 17a1202

File tree

7 files changed

+110
-1
lines changed

7 files changed

+110
-1
lines changed

‎tests/e2e/simple-app.test.ts‎

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expect, type Locator } from '@playwright/test'
1+
import { expect, type Locator,typeResponse } from '@playwright/test'
22
import { nextVersionSatisfies } from '../utils/next-version-helpers.mjs'
33
import { test } from '../utils/playwright-helpers.js'
44

@@ -282,3 +282,59 @@ test('can require CJS module that is not bundled', async ({ simple }) => {
282282
expect(parsedBody.notBundledCJSModule.isBundled).toEqual(false)
283283
expect(parsedBody.bundledCJSModule.isBundled).toEqual(true)
284284
})
285+
286+
test.describe('RSC cache poisoning', () => {
287+
test('Next.config.js rewrite', async ({ page, simple }) => {
288+
const prefetchResponsePromise = new Promise<Response>((resolve) => {
289+
page.on('response', (response) => {
290+
if (response.url().includes('/config-rewrite/source')) {
291+
resolve(response)
292+
}
293+
})
294+
})
295+
await page.goto(`${simple.url}/config-rewrite`)
296+
297+
// ensure prefetch
298+
await page.hover('text=NextConfig.rewrite')
299+
300+
// wait for prefetch request to finish
301+
const prefetchResponse = await prefetchResponsePromise
302+
303+
// ensure prefetch respond with RSC data
304+
expect(prefetchResponse.headers()['content-type']).toMatch(/text\/x-component/)
305+
expect(prefetchResponse.headers()['netlify-cdn-cache-control']).toMatch(/s-maxage=31536000/)
306+
307+
const htmlResponse = await page.goto(`${simple.url}/config-rewrite/source`)
308+
309+
// ensure we get HTML response
310+
expect(htmlResponse?.headers()['content-type']).toMatch(/text\/html/)
311+
expect(htmlResponse?.headers()['netlify-cdn-cache-control']).toMatch(/s-maxage=31536000/)
312+
})
313+
314+
test('Next.config.js redirect', async ({ page, simple }) => {
315+
const prefetchResponsePromise = new Promise<Response>((resolve) => {
316+
page.on('response', (response) => {
317+
if (response.url().includes('/config-redirect/dest')) {
318+
resolve(response)
319+
}
320+
})
321+
})
322+
await page.goto(`${simple.url}/config-redirect`)
323+
324+
// ensure prefetch
325+
await page.hover('text=NextConfig.redirect')
326+
327+
// wait for prefetch request to finish
328+
const prefetchResponse = await prefetchResponsePromise
329+
330+
// ensure prefetch respond with RSC data
331+
expect(prefetchResponse.headers()['content-type']).toMatch(/text\/x-component/)
332+
expect(prefetchResponse.headers()['netlify-cdn-cache-control']).toMatch(/s-maxage=31536000/)
333+
334+
const htmlResponse = await page.goto(`${simple.url}/config-rewrite/source`)
335+
336+
// ensure we get HTML response
337+
expect(htmlResponse?.headers()['content-type']).toMatch(/text\/html/)
338+
expect(htmlResponse?.headers()['netlify-cdn-cache-control']).toMatch(/s-maxage=31536000/)
339+
})
340+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default function Page() {
2+
return (
3+
<main>
4+
<h1>Hello redirect target</h1>
5+
</main>
6+
)
7+
}
8+
9+
export const dynamic = 'force-static'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Link from 'next/link'
2+
3+
export default function Home() {
4+
return (
5+
<div>
6+
<Link href="/config-redirect/source">NextConfig.redirect</Link>
7+
</div>
8+
)
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default function Page() {
2+
return (
3+
<main>
4+
<h1>Hello rewrite target</h1>
5+
</main>
6+
)
7+
}
8+
9+
export const dynamic = 'force-static'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Link from 'next/link'
2+
3+
export default function Home() {
4+
return (
5+
<div>
6+
<Link href="/config-rewrite/source">NextConfig.rewrite</Link>
7+
</div>
8+
)
9+
}

‎tests/fixtures/simple/next.config.js‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ const nextConfig = {
2929
destination: 'https://example.vercel.sh',
3030
basePath: false,
3131
},
32+
{
33+
source: '/config-rewrite/source',
34+
destination: '/config-rewrite/dest',
35+
},
36+
]
37+
},
38+
async redirects() {
39+
return [
40+
{
41+
source: '/config-redirect/source',
42+
destination: '/config-redirect/dest',
43+
permanent: true,
44+
},
3245
]
3346
},
3447
}

‎tests/integration/simple-app.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ test<FixtureTestContext>('Test that the simple next app is working', async (ctx)
101101
'/404',
102102
'/api/cached-permanent',
103103
'/api/cached-revalidate',
104+
'/config-redirect',
105+
'/config-redirect/dest',
106+
'/config-rewrite',
107+
'/config-rewrite/dest',
104108
'/image/local',
105109
'/image/migration-from-v4-runtime',
106110
'/image/remote-domain',

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /