Skip to content

Commit ec70096

Browse files
authored
Ensure unknown static paths 404 for data request (#16401)
We were accidentally allowing data requests to be rendered unconditionally. Instead, we should also check them against the staticPaths result and 404 when appropriate. --- Fixes #15383
1 parent fc98c13 commit ec70096

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

packages/next/next-server/server/next-server.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,6 @@ export default class Server {
11561156
fallbackMode !== 'blocking' &&
11571157
ssgCacheKey &&
11581158
!didRespond &&
1159-
!isDataReq &&
11601159
!isPreviewMode &&
11611160
isDynamicPathname &&
11621161
// Development should trigger fallback when the path is not in
@@ -1173,27 +1172,29 @@ export default class Server {
11731172
throw new NoFallbackError()
11741173
}
11751174

1176-
let html: string
1175+
if (!isDataReq) {
1176+
let html: string
11771177

1178-
// Production already emitted the fallback as static HTML.
1179-
if (isProduction) {
1180-
html = await this.incrementalCache.getFallback(pathname)
1181-
}
1182-
// We need to generate the fallback on-demand for development.
1183-
else {
1184-
query.__nextFallback = 'true'
1185-
if (isLikeServerless) {
1186-
prepareServerlessUrl(req, query)
1178+
// Production already emitted the fallback as static HTML.
1179+
if (isProduction) {
1180+
html = await this.incrementalCache.getFallback(pathname)
1181+
}
1182+
// We need to generate the fallback on-demand for development.
1183+
else {
1184+
query.__nextFallback = 'true'
1185+
if (isLikeServerless) {
1186+
prepareServerlessUrl(req, query)
1187+
}
1188+
const { value: renderResult } = await doRender()
1189+
html = renderResult.html
11871190
}
1188-
const { value: renderResult } = await doRender()
1189-
html = renderResult.html
1190-
}
11911191

1192-
sendPayload(req, res, html, 'html', {
1193-
generateEtags: this.renderOpts.generateEtags,
1194-
poweredByHeader: this.renderOpts.poweredByHeader,
1195-
})
1196-
return null
1192+
sendPayload(req, res, html, 'html', {
1193+
generateEtags: this.renderOpts.generateEtags,
1194+
poweredByHeader: this.renderOpts.poweredByHeader,
1195+
})
1196+
return null
1197+
}
11971198
}
11981199

11991200
const {

test/integration/prerender/test/index.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,32 @@ const runTests = (dev = false, isEmulatedServerless = false) => {
576576
expect(value).toMatch(/Hi \[second\]!/)
577577
})
578578

579+
if (!isEmulatedServerless) {
580+
it('should not return data for fallback: false and missing dynamic page', async () => {
581+
const res1 = await fetchViaHTTP(
582+
appPort,
583+
`/_next/data/${buildId}/dynamic/oopsie.json`
584+
)
585+
expect(res1.status).toBe(404)
586+
587+
await waitFor(500)
588+
589+
const res2 = await fetchViaHTTP(
590+
appPort,
591+
`/_next/data/${buildId}/dynamic/oopsie.json`
592+
)
593+
expect(res2.status).toBe(404)
594+
595+
await waitFor(500)
596+
597+
const res3 = await fetchViaHTTP(
598+
appPort,
599+
`/_next/data/${buildId}/dynamic/oopsie.json`
600+
)
601+
expect(res3.status).toBe(404)
602+
})
603+
}
604+
579605
it('should SSR catch-all page with brackets in param as string', async () => {
580606
const html = await renderViaHTTP(
581607
appPort,

0 commit comments

Comments
 (0)