Skip to content

Commit b029575

Browse files
committed
restore headers we use to set to try to produce output compatible for tests
1 parent 07d3a82 commit b029575

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

src/adapter/run/pages-and-app-handler.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,33 @@ const disableFaultyTransferEncodingHandling = (res: ComputeJsOutgoingMessage) =>
2626
}
2727
}
2828

29+
const getHeaderValueArray = (header: string): string[] => {
30+
return header
31+
.split(',')
32+
.map((value) => value.trim())
33+
.filter(Boolean)
34+
}
35+
36+
const omitHeaderValues = (header: string, values: string[]): string => {
37+
const headerValues = getHeaderValueArray(header)
38+
const filteredValues = headerValues.filter(
39+
(value) => !values.some((val) => value.startsWith(val)),
40+
)
41+
return filteredValues.join(', ')
42+
}
43+
44+
/**
45+
* https://httpwg.org/specs/rfc9211.html
46+
*
47+
* We get HIT, MISS, STALE statuses from Next cache.
48+
* We will ignore other statuses and will not set Cache-Status header in those cases.
49+
*/
50+
const NEXT_CACHE_TO_CACHE_STATUS: Record<string, string> = {
51+
HIT: `hit`,
52+
MISS: `fwd=miss`,
53+
STALE: `hit; fwd=stale`,
54+
}
55+
2956
type NextHandler = (
3057
req: IncomingMessage,
3158
res: ServerResponse,
@@ -39,6 +66,11 @@ export async function runNextHandler(
3966
context: Context,
4067
nextHandler: NextHandler,
4168
): Promise<Response> {
69+
console.log('Handling request', {
70+
url: request.url,
71+
isDataRequest: request.headers.get('x-nextjs-data'),
72+
})
73+
4274
const { req, res } = toReqRes(request)
4375
// Work around a bug in http-proxy in next@<14.0.2
4476
Object.defineProperty(req, 'connection', {
@@ -71,5 +103,50 @@ export async function runNextHandler(
71103
})
72104

73105
const response = await toComputeResponse(res)
106+
107+
{
108+
// move cache-control to cdn-cache-control
109+
const cacheControl = response.headers.get('cache-control')
110+
if (
111+
cacheControl &&
112+
['GET', 'HEAD'].includes(request.method) &&
113+
!response.headers.has('cdn-cache-control') &&
114+
!response.headers.has('netlify-cdn-cache-control')
115+
) {
116+
// handle CDN Cache Control on ISR and App Router page responses
117+
const browserCacheControl = omitHeaderValues(cacheControl, [
118+
's-maxage',
119+
'stale-while-revalidate',
120+
])
121+
const cdnCacheControl =
122+
// if we are serving already stale response, instruct edge to not attempt to cache that response
123+
response.headers.get('x-nextjs-cache') === 'STALE'
124+
? 'public, max-age=0, must-revalidate, durable'
125+
: [
126+
...getHeaderValueArray(cacheControl).map((value) =>
127+
value === 'stale-while-revalidate' ? 'stale-while-revalidate=31536000' : value,
128+
),
129+
'durable',
130+
].join(', ')
131+
132+
response.headers.set(
133+
'cache-control',
134+
browserCacheControl || 'public, max-age=0, must-revalidate',
135+
)
136+
response.headers.set('netlify-cdn-cache-control', cdnCacheControl)
137+
}
138+
}
139+
140+
{
141+
// set Cache-Status header based on Next.js cache status
142+
const nextCache = response.headers.get('x-nextjs-cache')
143+
if (nextCache) {
144+
if (nextCache in NEXT_CACHE_TO_CACHE_STATUS) {
145+
response.headers.set('cache-status', NEXT_CACHE_TO_CACHE_STATUS[nextCache])
146+
}
147+
response.headers.delete('x-nextjs-cache')
148+
}
149+
}
150+
74151
return response
75152
}

0 commit comments

Comments
 (0)