From 1f334d3fcd7049101fdba8a60a85eb98f66d6bef Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 23 Mar 2020 15:05:00 -0500 Subject: [PATCH 1/2] Update handling for ENOENT from GSSP methods --- packages/next/lib/coalesced-function.ts | 2 +- packages/next/next-server/server/render.tsx | 54 +++++++++++++------ .../getserversideprops/pages/enoent.js | 7 +++ .../getserversideprops/test/index.test.js | 13 +++++ 4 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 test/integration/getserversideprops/pages/enoent.js diff --git a/packages/next/lib/coalesced-function.ts b/packages/next/lib/coalesced-function.ts index b30fb4d40e0635f..d75a0c2ff307ed8 100644 --- a/packages/next/lib/coalesced-function.ts +++ b/packages/next/lib/coalesced-function.ts @@ -3,7 +3,7 @@ type CoalescedInvoke = { value: T } -type UnwrapPromise = T extends Promise ? U : T +export type UnwrapPromise = T extends Promise ? U : T const globalInvokeCache = new Map>>() diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index 920b6b70e130914..af9a878453ff204 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -38,6 +38,8 @@ import { tryGetPreviewData, __ApiPreviewProps } from './api-utils' import { getPageFiles } from './get-page-files' import { LoadComponentsReturnType, ManifestItem } from './load-components' import optimizeAmp from './optimize-amp' +import { UnwrapPromise } from '../../lib/coalesced-function' +import { GetStaticProps, GetServerSideProps } from '../../types' function noRouter() { const message = @@ -495,12 +497,23 @@ export async function renderToHTML( } if (isSSG && !isFallback) { - const data = await getStaticProps!({ - ...(pageIsDynamic ? { params: query as ParsedUrlQuery } : undefined), - ...(previewData !== false - ? { preview: true, previewData: previewData } - : undefined), - }) + let data: UnwrapPromise> + + try { + data = await getStaticProps!({ + ...(pageIsDynamic ? { params: query as ParsedUrlQuery } : undefined), + ...(previewData !== false + ? { preview: true, previewData: previewData } + : undefined), + }) + } catch (err) { + // remove not found error code to prevent triggering legacy + // 404 rendering + if (err.code === 'ENOENT') { + delete err.code + } + throw err + } const invalidKeys = Object.keys(data).filter( key => key !== 'revalidate' && key !== 'props' @@ -563,15 +576,26 @@ export async function renderToHTML( } if (getServerSideProps && !isFallback) { - const data = await getServerSideProps({ - req, - res, - query, - ...(pageIsDynamic ? { params: params as ParsedUrlQuery } : undefined), - ...(previewData !== false - ? { preview: true, previewData: previewData } - : undefined), - }) + let data: UnwrapPromise> + + try { + data = await getServerSideProps({ + req, + res, + query, + ...(pageIsDynamic ? { params: params as ParsedUrlQuery } : undefined), + ...(previewData !== false + ? { preview: true, previewData: previewData } + : undefined), + }) + } catch (err) { + // remove not found error code to prevent triggering legacy + // 404 rendering + if (err.code === 'ENOENT') { + delete err.code + } + throw err + } const invalidKeys = Object.keys(data).filter(key => key !== 'props') diff --git a/test/integration/getserversideprops/pages/enoent.js b/test/integration/getserversideprops/pages/enoent.js new file mode 100644 index 000000000000000..b8dde905c15f49c --- /dev/null +++ b/test/integration/getserversideprops/pages/enoent.js @@ -0,0 +1,7 @@ +export async function getServerSideProps() { + const error = new Error('oof') + error.code = 'ENOENT' + throw error +} + +export default () => 'hi' diff --git a/test/integration/getserversideprops/test/index.test.js b/test/integration/getserversideprops/test/index.test.js index 283560deff2416a..76f026ef5c52c6d 100644 --- a/test/integration/getserversideprops/test/index.test.js +++ b/test/integration/getserversideprops/test/index.test.js @@ -205,6 +205,19 @@ const runTests = (dev = false) => { expect(html).toMatch(/Post:.*?post-1/) }) + it('should handle throw ENOENT correctly', async () => { + const res = await fetchViaHTTP(appPort, '/enoent') + const html = await res.text() + + if (dev) { + expect(html).toContain('oof') + } else { + expect(res.status).toBe(500) + expect(html).toContain('Internal Server Error') + expect(html).not.toContain('This page could not be found') + } + }) + it('should have gssp in __NEXT_DATA__', async () => { const html = await renderViaHTTP(appPort, '/') const $ = cheerio.load(html) From 3e7c989071e1d3f9e3c817710da0e1fda0baaf81 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 23 Mar 2020 15:10:00 -0500 Subject: [PATCH 2/2] Add route to routes-manifest test --- test/integration/getserversideprops/test/index.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/integration/getserversideprops/test/index.test.js b/test/integration/getserversideprops/test/index.test.js index 76f026ef5c52c6d..cd123c5400da01b 100644 --- a/test/integration/getserversideprops/test/index.test.js +++ b/test/integration/getserversideprops/test/index.test.js @@ -78,6 +78,12 @@ const expectedManifestRoutes = () => [ ), page: '/default-revalidate', }, + { + dataRouteRegex: normalizeRegEx( + `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/enoent.json$` + ), + page: '/enoent', + }, { dataRouteRegex: normalizeRegEx( `^\\/_next\\/data\\/${escapeRegex(buildId)}\\/invalid-keys.json$`