Skip to content

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

+57-1
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, type Response } 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+
})
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'
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+
}
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'
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

+13
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

+4
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)