Skip to content

Commit 159aece

Browse files
fix: handle remote query redirects (#15222)
1 parent 539b78f commit 159aece

File tree

4 files changed

+38
-2
lines changed

4 files changed

+38
-2
lines changed

.changeset/quiet-swans-render.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+
fix: avoid triggering `handleError` when redirecting in a remote function

packages/kit/src/runtime/server/page/index.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { text } from '@sveltejs/kit';
2-
import { Redirect } from '@sveltejs/kit/internal';
2+
import { HttpError, Redirect } from '@sveltejs/kit/internal';
33
import { compact } from '../../../utils/array.js';
44
import { get_status, normalize_error } from '../../../utils/error.js';
55
import { add_data_suffix } from '../../pathname.js';
@@ -357,6 +357,11 @@ export async function render_page(
357357
ssr === false ? server_data_serializer(event, event_state, options) : data_serializer
358358
});
359359
} catch (e) {
360+
// a remote function could have thrown a redirect during render
361+
if (e instanceof Redirect) {
362+
return redirect_response(e.status, e.location);
363+
}
364+
360365
// if we end up here, it means the data loaded successfully
361366
// but the page failed to render, or that a prerendering error occurred
362367
return await respond_with_error({
@@ -365,7 +370,7 @@ export async function render_page(
365370
options,
366371
manifest,
367372
state,
368-
status: 500,
373+
status: e instanceof HttpError ? e.status : 500,
369374
error: e,
370375
resolve_opts
371376
});

packages/kit/test/apps/async/src/hooks.server.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import { isRedirect } from '@sveltejs/kit';
2+
13
/** @type {import('@sveltejs/kit').HandleValidationError} */
24
export const handleValidationError = ({ issues }) => {
35
return { message: issues[0].message };
46
};
57

68
/** @type {import('@sveltejs/kit').HandleServerError} */
79
export const handleError = ({ error: e, status, message }) => {
10+
// helps us catch sveltekit redirects thrown in component code
11+
if (isRedirect(e)) {
12+
throw new Error("Redirects shouldn't trigger the handleError hook");
13+
}
14+
815
const error = /** @type {Error} */ (e);
916

1017
return { message: `${error.message} (${status} ${message})` };

packages/kit/test/apps/async/test/test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import http from 'node:http';
12
import { expect } from '@playwright/test';
23
import { test } from '../../../utils.js';
34

@@ -25,6 +26,24 @@ test.describe('remote functions', () => {
2526
await expect(page.locator('#redirected')).toHaveText('redirected');
2627
});
2728

29+
test("query that's awaited and throws a redirect doesn't trigger handleError hook", async ({
30+
baseURL
31+
}) => {
32+
const { status, location } = await new Promise((fulfil, reject) => {
33+
const request = http.get(`${baseURL}/remote/query-redirect/from-page`, (response) => {
34+
fulfil({
35+
status: response.statusCode,
36+
location: response.headers.location
37+
});
38+
response.resume();
39+
});
40+
request.on('error', reject);
41+
});
42+
43+
expect(status).toBe(307);
44+
expect(location).toBe('/remote/query-redirect/redirected');
45+
});
46+
2847
test('non-exported queries do not clobber each other', async ({ page }) => {
2948
await page.goto('/remote/query-non-exported');
3049

0 commit comments

Comments
 (0)