Skip to content

Commit e9b8c65

Browse files
authored
[fix] Handle throw error/redirect in +server.js (#6028)
Fixes #5993
1 parent b882e1c commit e9b8c65

File tree

5 files changed

+59
-10
lines changed

5 files changed

+59
-10
lines changed

.changeset/honest-parrots-compare.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
Handle `throw error/redirect` in `+server.js`

packages/kit/src/runtime/server/endpoint.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { HttpError, Redirect } from '../../index/private.js';
12
import { check_method_names, method_not_allowed } from './utils.js';
23

34
/**
@@ -29,16 +30,29 @@ export async function render_endpoint(event, route) {
2930
return method_not_allowed(mod, method);
3031
}
3132

32-
const response = await handler(
33-
/** @type {import('types').RequestEvent<Record<string, any>>} */ (event)
34-
);
35-
36-
if (!(response instanceof Response)) {
37-
return new Response(
38-
`Invalid response from route ${event.url.pathname}: handler should return a Response object`,
39-
{ status: 500 }
33+
try {
34+
const response = await handler(
35+
/** @type {import('types').RequestEvent<Record<string, any>>} */ (event)
4036
);
41-
}
4237

43-
return response;
38+
if (!(response instanceof Response)) {
39+
return new Response(
40+
`Invalid response from route ${event.url.pathname}: handler should return a Response object`,
41+
{ status: 500 }
42+
);
43+
}
44+
45+
return response;
46+
} catch (error) {
47+
if (error instanceof HttpError) {
48+
return new Response(error.message, { status: error.status });
49+
} else if (error instanceof Redirect) {
50+
return new Response(undefined, {
51+
status: error.status,
52+
headers: { Location: error.location }
53+
});
54+
} else {
55+
throw error;
56+
}
57+
}
4458
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { error } from '@sveltejs/kit';
2+
3+
export function GET() {
4+
throw error(401, 'You shall not pass');
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { redirect } from '@sveltejs/kit';
2+
3+
export function GET() {
4+
throw redirect(302, '/');
5+
}

packages/kit/test/apps/basics/test/server.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,26 @@ test.describe('Errors', () => {
147147
'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\')"'
148148
);
149149
});
150+
151+
test('throw error(..) in endpoint', async ({ page, read_errors }) => {
152+
const res = await page.goto('/errors/endpoint-throw-error');
153+
154+
const error = read_errors('/errors/endpoint-throw-error');
155+
expect(error).toBe(undefined);
156+
157+
expect(await res?.text()).toBe('You shall not pass');
158+
expect(res?.status()).toBe(401);
159+
});
160+
161+
test('throw redirect(..) in endpoint', async ({ page, read_errors }) => {
162+
const res = await page.goto('/errors/endpoint-throw-redirect');
163+
expect(res?.status()).toBe(200); // redirects are opaque to the browser
164+
165+
const error = read_errors('/errors/endpoint-throw-redirect');
166+
expect(error).toBe(undefined);
167+
168+
expect(await page.textContent('h1')).toBe('the answer is 42');
169+
});
150170
});
151171

152172
test.describe('Load', () => {

0 commit comments

Comments
 (0)