From fd195526cd9de6c56e1daa7ba655828464b67ecd Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sun, 17 Sep 2023 02:49:07 +0800 Subject: [PATCH] fix: differentiate between `404` and `500` when rendering an error page (#10565) --- .changeset/hip-tips-drum.md | 5 +++++ .../kit/src/runtime/server/page/respond_with_error.js | 5 +++++ packages/kit/src/runtime/server/respond.js | 8 ++++++++ packages/kit/test/apps/basics/src/app.d.ts | 1 + packages/kit/test/apps/basics/src/hooks.server.js | 6 ++++++ .../kit/test/apps/basics/src/routes/+layout.server.js | 10 +++++++++- packages/kit/test/apps/basics/test/test.js | 10 ++++++++++ 7 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .changeset/hip-tips-drum.md diff --git a/.changeset/hip-tips-drum.md b/.changeset/hip-tips-drum.md new file mode 100644 index 000000000000..c0a1acfb1890 --- /dev/null +++ b/.changeset/hip-tips-drum.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: correctly return 404 when navigating to a missing page and the root layout fetches a prerendered endpoint diff --git a/packages/kit/src/runtime/server/page/respond_with_error.js b/packages/kit/src/runtime/server/page/respond_with_error.js index 15148b379bf9..f1475cc5bb76 100644 --- a/packages/kit/src/runtime/server/page/respond_with_error.js +++ b/packages/kit/src/runtime/server/page/respond_with_error.js @@ -28,6 +28,11 @@ export async function respond_with_error({ error, resolve_opts }) { + // reroute to the fallback page to prevent an infinite chain of requests. + if (event.request.headers.get('x-sveltekit-error')) { + return static_error_page(options, status, /** @type {Error} */ (error).message); + } + /** @type {import('./types').Fetched[]} */ const fetched = []; diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js index 16cc5f91932b..7967658c77f1 100644 --- a/packages/kit/src/runtime/server/respond.js +++ b/packages/kit/src/runtime/server/respond.js @@ -457,6 +457,14 @@ export async function respond(request, options, manifest, state) { return response; } + if (state.error && event.isSubRequest) { + return await fetch(request, { + headers: { + 'x-sveltekit-error': 'true' + } + }); + } + if (state.error) { return text('Internal Server Error', { status: 500 diff --git a/packages/kit/test/apps/basics/src/app.d.ts b/packages/kit/test/apps/basics/src/app.d.ts index b0b67f6fff90..adba879735d9 100644 --- a/packages/kit/test/apps/basics/src/app.d.ts +++ b/packages/kit/test/apps/basics/src/app.d.ts @@ -5,6 +5,7 @@ declare global { name?: string; key: string; params: Record; + url?: URL; } interface Platform {} diff --git a/packages/kit/test/apps/basics/src/hooks.server.js b/packages/kit/test/apps/basics/src/hooks.server.js index c684719ed476..46bac8eeaf56 100644 --- a/packages/kit/test/apps/basics/src/hooks.server.js +++ b/packages/kit/test/apps/basics/src/hooks.server.js @@ -128,6 +128,12 @@ export const handle = sequence( throw redirect(303, '/actions/enhance'); } + return resolve(event); + }, + async ({ event, resolve }) => { + if (['/non-existent-route', '/non-existent-route-loop'].includes(event.url.pathname)) { + event.locals.url = new URL(event.request.url); + } return resolve(event); } ); diff --git a/packages/kit/test/apps/basics/src/routes/+layout.server.js b/packages/kit/test/apps/basics/src/routes/+layout.server.js index f6d2446b6ab8..5700a931f816 100644 --- a/packages/kit/test/apps/basics/src/routes/+layout.server.js +++ b/packages/kit/test/apps/basics/src/routes/+layout.server.js @@ -12,7 +12,15 @@ if (JSON.parse(env.SOME_JSON).answer !== 42) { } /** @type {import('./$types').LayoutServerLoad} */ -export async function load({ cookies }) { +export async function load({ cookies, locals, fetch }) { + if (locals.url?.pathname === '/non-existent-route') { + await fetch('/prerendering/prerendered-endpoint/api').then((r) => r.json()); + } + + if (locals.url?.pathname === '/non-existent-route-loop') { + await fetch('/non-existent-route-loop'); + } + const should_fail = cookies.get('fail-type'); if (should_fail) { cookies.delete('fail-type', { path: '/' }); diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index 79bcd7c6f89a..971058ba1870 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -515,6 +515,16 @@ test.describe('Load', () => { expect(await page.textContent('p')).toBe('error: false'); }); + + test('404 and root layout load fetch to prerendered endpoint works', async ({ page }) => { + await page.goto('/non-existent-route'); + + expect(await page.textContent('h1')).toBe('404'); + + await page.goto('/non-existent-route-loop'); + + expect(await page.textContent('h1')).toBe('404'); + }); }); test.describe('Nested layouts', () => {