Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: differentiate between 404 and 500 when rendering an error page #10565

Merged
merged 11 commits into from
Sep 16, 2023
5 changes: 5 additions & 0 deletions .changeset/hip-tips-drum.md
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions packages/kit/src/runtime/server/page/respond_with_error.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];

Expand Down
8 changes: 8 additions & 0 deletions packages/kit/src/runtime/server/respond.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions packages/kit/test/apps/basics/src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare global {
name?: string;
key: string;
params: Record<string, string>;
url?: URL;
}

interface Platform {}
Expand Down
6 changes: 6 additions & 0 deletions packages/kit/test/apps/basics/src/hooks.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
);
Expand Down
10 changes: 9 additions & 1 deletion packages/kit/test/apps/basics/src/routes/+layout.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: '/' });
Expand Down
10 changes: 10 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down