Skip to content

Commit

Permalink
fix: added cache control headers for static app routes (#72521)
Browse files Browse the repository at this point in the history
This pull request includes several changes to improve cache control
handling and add new test cases for verifying cache headers in the
standalone mode of the application.

Improvements to cache control handling:

*
[`packages/next/src/server/base-server.ts`](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3295-R3298):
Updated cache control conditions to check for `undefined` explicitly
before setting cache headers.
[[1]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3295-R3298)
[[2]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aL3318-R3324)
[[3]](diffhunk://#diff-6f4291cc2bfc5073fdca12a014011769e840ee68583db1468acef075f037015aR3354-R3365)

New test cases:

*
[`test/production/standalone-mode/required-server-files/required-server-files-app.test.ts`](diffhunk://#diff-0d083b6c7bd3a8a3e9c5ee854123ada3b72db58220d8b65912b047b082f834a2R104-R129):
Added test cases to verify that the correct cache headers are sent for
app routes and app pages.

New static and dynamic route handlers:

*
`test/production/standalone-mode/required-server-files/app/api/test/[slug]/route.js`:
Added a new dynamic route handler with forced static generation.
([test/production/standalone-mode/required-server-files/app/api/test/[slug]/route.jsR1-R7](diffhunk://#diff-1cf8a2cfdbb6473656b2456af0267556270fbbaa7ee2c37e2f3e6c6fed1e4d21R1-R7))
*
`test/production/standalone-mode/required-server-files/app/test/[slug]/page.jsx`:
Added a new static page with a revalidation interval and a function to
generate static parameters.
([test/production/standalone-mode/required-server-files/app/test/[slug]/page.jsxR1-R9](diffhunk://#diff-32038443ca3e4f28db37a6543966397682c64cf6f34e6dd03fd8096414d23022R1-R9))

- Fixes #65814

Co-authored-by: Janka Uryga <[email protected]>
Co-authored-by: Sam Ko <[email protected]>
  • Loading branch information
3 people authored Nov 10, 2024
1 parent 0fc77d9 commit 91e3479
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 5 deletions.
32 changes: 27 additions & 5 deletions packages/next/src/server/base-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3292,7 +3292,10 @@ export default abstract class Server<

// If cache control is already set on the response we don't
// override it to allow users to customize it via next.config
if (cacheEntry.revalidate && !res.getHeader('Cache-Control')) {
if (
typeof cacheEntry.revalidate !== 'undefined' &&
!res.getHeader('Cache-Control')
) {
res.setHeader(
'Cache-Control',
formatRevalidate({
Expand All @@ -3315,7 +3318,10 @@ export default abstract class Server<
} else if (cachedData.kind === CachedRouteKind.REDIRECT) {
// If cache control is already set on the response we don't
// override it to allow users to customize it via next.config
if (cacheEntry.revalidate && !res.getHeader('Cache-Control')) {
if (
typeof cacheEntry.revalidate !== 'undefined' &&
!res.getHeader('Cache-Control')
) {
res.setHeader(
'Cache-Control',
formatRevalidate({
Expand All @@ -3339,17 +3345,33 @@ export default abstract class Server<
return null
}
} else if (cachedData.kind === CachedRouteKind.APP_ROUTE) {
const headers = { ...cachedData.headers }
const headers = fromNodeOutgoingHttpHeaders(cachedData.headers)

if (!(this.minimalMode && isSSG)) {
delete headers[NEXT_CACHE_TAGS_HEADER]
headers.delete(NEXT_CACHE_TAGS_HEADER)
}

// If cache control is already set on the response we don't
// override it to allow users to customize it via next.config
if (
typeof cacheEntry.revalidate !== 'undefined' &&
!res.getHeader('Cache-Control') &&
!headers.get('Cache-Control')
) {
headers.set(
'Cache-Control',
formatRevalidate({
revalidate: cacheEntry.revalidate,
expireTime: this.nextConfig.expireTime,
})
)
}

await sendResponse(
req,
res,
new Response(cachedData.body, {
headers: fromNodeOutgoingHttpHeaders(headers),
headers,
status: cachedData.status || 200,
})
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const dynamic = 'force-static'

export async function GET(request, context) {
const { params } = context
const { slug } = params
return Response.json({ message: `Hello, ${slug}!` })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const revalidate = 3600

export default function Page() {
return <div>Hello, World!</div>
}

export async function generateStaticParams() {
return []
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,32 @@ describe('required server files app router', () => {
if (server) await killApp(server)
})

it('should send the right cache headers for an app route', async () => {
const res = await fetchViaHTTP(appPort, '/api/test/123', undefined, {
headers: {
'x-matched-path': '/api/test/[slug]',
'x-now-route-matches': '1=123&nxtPslug=123',
},
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=31536000, stale-while-revalidate'
)
})

it('should send the right cache headers for an app page', async () => {
const res = await fetchViaHTTP(appPort, '/test/123', undefined, {
headers: {
'x-matched-path': '/test/[slug]',
'x-now-route-matches': '1=123&nxtPslug=123',
},
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=3600, stale-while-revalidate'
)
})

it('should not fail caching', async () => {
expect(next.cliOutput).not.toContain('ERR_INVALID_URL')
})
Expand Down
2 changes: 2 additions & 0 deletions test/turbopack-build-tests-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16578,6 +16578,8 @@
"test/production/standalone-mode/required-server-files/required-server-files-app.test.ts": {
"passed": [],
"failed": [
"required server files app router should send the right cache headers for an app route",
"required server files app router should send the right cache headers for an app page",
"required server files app router should not fail caching",
"required server files app router should not send cache tags in minimal mode for SSR",
"required server files app router should not send invalid soft tags to cache handler",
Expand Down

0 comments on commit 91e3479

Please sign in to comment.