kit
kit copied to clipboard
Clientside link navigation doesn't respect redirects
Describe the bug
When using SvelteKit's clientside link navigation, redirects are not being respected unless the link has the data-sveltekit-reload attribute. If a page returns a redirect, Kit just throws a 500 Internal Error for the user (no message on the server). You can verify that the responses are getting sent correctly and have 3xx status codes by checking devtools.
This happens both when redirecting from hooks.server.ts and +page.server.ts.
When using the data-sveltekit-reload or manually refreshing the page, the redirect works fine.
It doesn't seem to matter how the redirect is sent: Kit's redirect() error, Response(null, { status: 302, headers: { Location: '/login' } }), and Response.redirect(event.url.origin + '/login', 302); all give the same result.
I couldn't find any docs on this, so I assume this is either unintended behavior or I'm doing something wrong.
Reproduction
https://github.com/styxpilled/sveltekit-navigation-redirect-issue
Logs
No response
System Info
System:
OS: Windows 10 10.0.19044
CPU: (4) x64 Intel(R) Core(TM) i3-9100F CPU @ 3.60GHz
Memory: 453.96 MB / 15.94 GB
Binaries:
Node: 18.11.0 - ~\AppData\Local\pnpm\node.EXE
npm: 8.19.2 - ~\AppData\Local\pnpm\npm.CMD
Browsers:
Edge: Spartan (44.19041.1266.0), Chromium (107.0.1418.56)
Internet Explorer: 11.0.19041.1566
Severity
annoyance
Additional Information
No response
The issue happens when clicking the link, the router always makes a request to /.../__data.json and expects JSON, but hooks.server is returning HTML because of the redirect.
// error log in the browser
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
https://stackblitz.com/edit/sveltejs-kit-template-default-1hgftc?file=README.md,src%2Fhooks.server.js&terminal=dev
This is marked as fixed, but I am still having issues with redirects in client-side navigation. I have simple link like this:
<a href="/signout?u={encodeURIComponent($page.url.href)}">Sign Out</a>
And I have a routes/signout/+page.server.ts with:
import db from "$lib/server/db";
import { signOut } from "$lib/server/user-session";
import { redirect } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ cookies, url }) => {
await signOut(db, cookies);
throw redirect(302, url.searchParams.get("u") ?? "/");
};
I am using version 1.0.0-next.571 of SvelteKit.
Edit: I can see that __data.json no longer throws an error, it is now json with the redirect info. However no navigation takes place, user is still on the same page as if nothing changed. Is this because I am sending the user to the same URL?
This is marked as fixed, but I am still having issues with redirects in client-side navigation. I have simple link like this:
<a href="/signout?u={encodeURIComponent($page.url.href)}">Sign Out</a>And I have a
routes/signout/+page.server.tswith:import db from "$lib/server/db"; import { signOut } from "$lib/server/user-session"; import { redirect } from "@sveltejs/kit"; import type { PageServerLoad } from "./$types"; export const load: PageServerLoad = async ({ cookies, url }) => { await signOut(db, cookies); throw redirect(302, url.searchParams.get("u") ?? "/"); };I am using version
1.0.0-next.571of SvelteKit.Edit: I can see that
__data.jsonno longer throws an error, it is now json with the redirect info. However no navigation takes place, user is still on the same page as if nothing changed. Is this because I am sending the user to the same URL?
I've tried reproducing the issue here https://stackblitz.com/edit/sveltejs-kit-template-default-vasxyy?file=src/routes/+page.svelte
It is redirecting to the same URL. Is this what you've intended?
If you need to reload data after the signout, you could include a invalidateAll() or change it to a POST form action. I've read that a POST is preferable for a signout because it signifies that there are side-effects. It also avoids the issue of the signout load function being preloaded (calling a signout to the db) when the user hovers over the link. This happens because of SvelteKit's preload link options, which you can also turn off manually or omit from app.html.
Yep I understand now, this is my own mistake.
Also, I saw in your code there a bug I overlooked, thanks! One of those weird times where || is actually better than ??.