Skip to content

Commit

Permalink
Update handling for ENOENT from GSSP methods (#11302)
Browse files Browse the repository at this point in the history
* Update handling for ENOENT from GSSP methods

* Add route to routes-manifest test
  • Loading branch information
ijjk committed Mar 24, 2020
1 parent aadb31f commit b4fca31
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 16 deletions.
2 changes: 1 addition & 1 deletion packages/next/lib/coalesced-function.ts
Expand Up @@ -3,7 +3,7 @@ type CoalescedInvoke<T> = {
value: T
}

type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T

const globalInvokeCache = new Map<string, Promise<CoalescedInvoke<unknown>>>()

Expand Down
54 changes: 39 additions & 15 deletions packages/next/next-server/server/render.tsx
Expand Up @@ -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 =
Expand Down Expand Up @@ -497,12 +499,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<ReturnType<GetStaticProps>>

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'
Expand Down Expand Up @@ -565,15 +578,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<ReturnType<GetServerSideProps>>

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')

Expand Down
7 changes: 7 additions & 0 deletions 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'
19 changes: 19 additions & 0 deletions test/integration/getserversideprops/test/index.test.js
Expand Up @@ -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$`
Expand Down Expand Up @@ -205,6 +211,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)
Expand Down

0 comments on commit b4fca31

Please sign in to comment.