diff --git a/packages/kit/src/runtime/server/endpoint.js b/packages/kit/src/runtime/server/endpoint.js index d29003cbc4de..91c7d9953742 100644 --- a/packages/kit/src/runtime/server/endpoint.js +++ b/packages/kit/src/runtime/server/endpoint.js @@ -75,7 +75,22 @@ export async function render_endpoint(event, mod) { }); } - const response = await handler(event); + let response; + try { + response = await handler(event); + } catch (err) { + const parsed_status = parseInt(err.status); + if (isNaN(parsed_status)) { + throw err; + } + response = { + status: parsed_status, + headers: err.headers, + body: err.body, + error: err.error + }; + } + const preface = `Invalid response from route ${event.url.pathname}`; if (typeof response !== 'object') { diff --git a/packages/kit/test/apps/basics/src/routes/endpoint-output/thrown-ok.js b/packages/kit/test/apps/basics/src/routes/endpoint-output/thrown-ok.js new file mode 100644 index 000000000000..a79fd6290ec8 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/endpoint-output/thrown-ok.js @@ -0,0 +1,7 @@ +/** @type {import('@sveltejs/kit').RequestHandler} */ +export function get() { + const err = new Error(); + err.status = 200; + err.body = { hello: 'world' }; + throw err; +} diff --git a/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.json.js b/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.json.js new file mode 100644 index 000000000000..06635c7c0364 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.json.js @@ -0,0 +1,6 @@ +/** @type {import('@sveltejs/kit').RequestHandler} */ +export function get() { + const err = new Error(); + err.status = 555; + throw err; +} diff --git a/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.svelte b/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.svelte new file mode 100644 index 000000000000..84d547f38668 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/endpoint-thrown-not-ok.svelte @@ -0,0 +1,18 @@ + + +

this text should not appear

diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index e9b0e2c71b9b..698f51e43bbf 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -626,6 +626,12 @@ test.describe.parallel('Endpoints', () => { expect(await response.json()).toEqual({}); }); + test('200 status on thrown response', async ({ request }) => { + const response = await request.get('/endpoint-output/thrown-ok'); + expect(/** @type {import('@playwright/test').APIResponse} */ (response).status()).toBe(200); + expect(await response.json()).toEqual({ hello: 'world' }); + }); + test('set-cookie without body', async ({ request }) => { const response = await request.get('/endpoint-output/headers'); expect(/** @type {import('@playwright/test').APIResponse} */ (response).status()).toBe(200); @@ -1002,6 +1008,24 @@ test.describe.parallel('Errors', () => { } }); + test('thrown not ok response from endpoint', async ({ page, read_errors }) => { + const res = await page.goto('/errors/endpoint-thrown-not-ok'); + + expect(read_errors('/errors/endpoint-not-ok.json')).toBeUndefined(); + + expect(res && res.status()).toBe(555); + expect(await page.textContent('#message')).toBe('This is your custom error page saying: ""'); + + const contents = await page.textContent('#stack'); + const location = /endpoint-thrown-not-ok\.svelte:12:9|endpoint-thrown-not-ok\.svelte:12:15/; // TODO: Remove second location with Vite 2.9 + + if (process.env.DEV) { + expect(contents).toMatch(location); + } else { + expect(contents).not.toMatch(location); + } + }); + test('error in shadow endpoint', async ({ page, read_errors }) => { const res = await page.goto('/errors/endpoint-shadow');