Skip to content

Commit 70f9b15

Browse files
authored
fix: add debug information around potential html/rsc response mismatches (#2816)
1 parent 530d2c5 commit 70f9b15

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

src/run/handlers/cache.cts

+12
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
332332
}
333333
}
334334
case 'APP_PAGE': {
335+
const requestContext = getRequestContext()
336+
if (requestContext && blob.value?.kind === 'APP_PAGE') {
337+
requestContext.isCacheableAppPage = true
338+
}
339+
335340
const { revalidate, rscData, ...restOfPageValue } = blob.value
336341

337342
span.addEvent(blob.value?.kind, { lastModified: blob.lastModified, revalidate, ttl })
@@ -410,6 +415,13 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
410415

411416
await this.cacheStore.set(key, { lastModified, value }, 'blobStore.set')
412417

418+
if (data?.kind === 'APP_PAGE') {
419+
const requestContext = getRequestContext()
420+
if (requestContext) {
421+
requestContext.isCacheableAppPage = true
422+
}
423+
}
424+
413425
if ((!data && !isDataReq) || data?.kind === 'PAGE' || data?.kind === 'PAGES') {
414426
const requestContext = getRequestContext()
415427
if (requestContext?.didPagesRouterOnDemandRevalidate) {

src/run/handlers/request-context.cts

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type RequestContext = {
3535
backgroundWorkPromise: Promise<unknown>
3636
logger: SystemLogger
3737
requestID: string
38+
isCacheableAppPage?: boolean
3839
}
3940

4041
type RequestContextAsyncLocalStorage = AsyncLocalStorage<RequestContext>

src/run/handlers/server.ts

+36-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { nextResponseProxy } from '../revalidate.js'
1717
import { setFetchBeforeNextPatchedIt } from '../storage/storage.cjs'
1818

1919
import { getLogger, type RequestContext } from './request-context.cjs'
20-
import { getTracer } from './tracer.cjs'
20+
import { getTracer, recordWarning } from './tracer.cjs'
2121
import { setupWaitUntil } from './wait-until.cjs'
2222

2323
setFetchBeforeNextPatchedIt(globalThis.fetch)
@@ -117,11 +117,6 @@ export default async (
117117
const nextCache = response.headers.get('x-nextjs-cache')
118118
const isServedFromNextCache = nextCache === 'HIT' || nextCache === 'STALE'
119119

120-
topLevelSpan.setAttributes({
121-
'x-nextjs-cache': nextCache ?? undefined,
122-
isServedFromNextCache,
123-
})
124-
125120
if (isServedFromNextCache) {
126121
await adjustDateHeader({
127122
headers: response.headers,
@@ -136,6 +131,41 @@ export default async (
136131
setVaryHeaders(response.headers, request, nextConfig)
137132
setCacheStatusHeader(response.headers, nextCache)
138133

134+
const netlifyVary = response.headers.get('netlify-vary') ?? undefined
135+
const netlifyCdnCacheControl = response.headers.get('netlify-cdn-cache-control') ?? undefined
136+
topLevelSpan.setAttributes({
137+
'x-nextjs-cache': nextCache ?? undefined,
138+
isServedFromNextCache,
139+
netlifyVary,
140+
netlifyCdnCacheControl,
141+
})
142+
143+
if (requestContext.isCacheableAppPage) {
144+
const isRSCRequest = request.headers.get('rsc') === '1'
145+
const contentType = response.headers.get('content-type') ?? undefined
146+
147+
const isExpectedContentType =
148+
((isRSCRequest && contentType?.includes('text/x-component')) ||
149+
(!isRSCRequest && contentType?.includes('text/html'))) ??
150+
false
151+
152+
topLevelSpan.setAttributes({
153+
isRSCRequest,
154+
isCacheableAppPage: true,
155+
contentType,
156+
isExpectedContentType,
157+
})
158+
159+
if (!isExpectedContentType) {
160+
recordWarning(
161+
new Error(
162+
`Unexpected content type was produced for App Router page response (isRSCRequest: ${isRSCRequest}, contentType: ${contentType})`,
163+
),
164+
topLevelSpan,
165+
)
166+
}
167+
}
168+
139169
async function waitForBackgroundWork() {
140170
// it's important to keep the stream open until the next handler has finished
141171
await nextHandlerPromise

0 commit comments

Comments
 (0)