From e50ad14afab9efa9054f76d6ce64cfcb504b01c4 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 6 Sep 2024 14:56:37 -0700 Subject: [PATCH] Fix middleware fallback: false case (#69799) This ensures we properly set the request meta during our middleware invoke so that the `NoFallbackError` bubbling is handled properly. Without these fields set we bubble the error unexpectedly causing an unexpected 500 instead of a 404. x-ref: https://github.com/vercel/next.js/pull/66987 Closes: https://github.com/vercel/next.js/issues/69428 --- .../server/lib/router-utils/resolve-routes.ts | 3 ++ .../app/pages/ssg-fallback-false/[slug].js | 53 +++++++++++++++++++ .../e2e/middleware-general/test/index.test.ts | 9 ++++ 3 files changed, 65 insertions(+) create mode 100644 test/e2e/middleware-general/app/pages/ssg-fallback-false/[slug].js diff --git a/packages/next/src/server/lib/router-utils/resolve-routes.ts b/packages/next/src/server/lib/router-utils/resolve-routes.ts index 1250838f93447..7b9d119eb2d54 100644 --- a/packages/next/src/server/lib/router-utils/resolve-routes.ts +++ b/packages/next/src/server/lib/router-utils/resolve-routes.ts @@ -471,6 +471,9 @@ export function getResolveRoutes( throw new Error(`Failed to initialize render server "middleware"`) } + addRequestMeta(req, 'invokePath', '') + addRequestMeta(req, 'invokeOutput', '') + addRequestMeta(req, 'invokeQuery', {}) addRequestMeta(req, 'middlewareInvoke', true) debug('invoking middleware', req.url, req.headers) diff --git a/test/e2e/middleware-general/app/pages/ssg-fallback-false/[slug].js b/test/e2e/middleware-general/app/pages/ssg-fallback-false/[slug].js new file mode 100644 index 0000000000000..ac8f4401f31db --- /dev/null +++ b/test/e2e/middleware-general/app/pages/ssg-fallback-false/[slug].js @@ -0,0 +1,53 @@ +import { useRouter } from 'next/router' +import { useEffect } from 'react' +import { useState } from 'react' + +export default function Page(props) { + const router = useRouter() + const [asPath, setAsPath] = useState( + router.isReady ? router.asPath : router.href + ) + + if (!props.params) { + console.error('props', props) + throw new Error('missing props!!!') + } + + useEffect(() => { + if (router.isReady) { + setAsPath(router.asPath) + } + }, [router.asPath, router.isReady]) + + return ( + <> +

/blog/[slug]

+

{JSON.stringify(router.query)}

+

{router.pathname}

+

{asPath}

+

{JSON.stringify(props)}

+ + ) +} + +export function getStaticProps({ params }) { + if (params.slug.includes('not-found')) { + return { + notFound: true, + } + } + + return { + props: { + now: Date.now(), + params, + }, + } +} + +export function getStaticPaths() { + return { + paths: ['/ssg-fallback-false/first', '/ssg-fallback-false/hello'], + fallback: false, + } +} diff --git a/test/e2e/middleware-general/test/index.test.ts b/test/e2e/middleware-general/test/index.test.ts index 8112918dcdfb9..70e5c8a2590f9 100644 --- a/test/e2e/middleware-general/test/index.test.ts +++ b/test/e2e/middleware-general/test/index.test.ts @@ -102,6 +102,15 @@ describe('Middleware Runtime', () => { } function runTests({ i18n }: { i18n?: boolean }) { + it('should handle 404 on fallback: false route correctly', async () => { + const res = await next.fetch('/ssg-fallback-false/first') + expect(res.status).toBe(200) + expect(await res.text()).toContain('blog') + + const res2 = await next.fetch('/ssg-fallback-false/non-existent') + expect(res2.status).toBe(404) + }) + it('should work with notFound: true correctly', async () => { const browser = await next.browser('/ssr-page') await browser.eval('window.next.router.push("/ssg/not-found-1")')