I have a problem with redirecting after submitting form in SvelteKit.
I have some routes that needs authentication, before rendering it I'm checking if user is authenticated.
routes│ ├──+page.svelte│ ├── login│ │ ├──+page.server.ts│ │ └──+page.svelte│ └── movies│ ├──+page.server.ts│ ├──+page.svelte│ └── [id]│ ├──+page.server.ts│ ├──+page.svelte│ └──+page.ts
For example, when user vistits /movies
route, in my +page.server.ts
I'm checking if user is authenticated, by lookup in cookies. If cookies haven't auth_token
I'm redirecting him to /login
route with some info about desired redirecting route after succesful login.
So in that scenario, user will be redirected to /login?redirectTo=%2Fmovies
For that part, everything works great.
The idea is that, if he authenticate it should redirect him again to /movies
route.
I wrote some logic in routes/login/+page.server.ts
to gather value of redirectTo
query param but after submitting form I can't see it.
/routes/login/+page.server.ts
import { redirect } from '@sveltejs/kit'; export const actions = { login: async ({request, cookies, url}) => { console.log("url", url) console.log('request', request) const formData = await request.formData(); const data = { email: formData.get('email'), password: formData.get('password')} const response = await fetch("http://localhost:4000/v1/tokens/authentication", { method: 'POST', headers: {'Content-Type': 'application/json' }, body: JSON.stringify(data), credentials: 'include' }) if (!response.ok) { return {success: false}; } const cookie = response.headers.get('set-cookie'); if (cookie !== null) { const parts = cookie.split(';'); const token = parts[0].split('=')[1]; const expires = parts.find(p => p.trim().startsWith('Expires'))?.split('=')[1]; cookies.set('auth_token', token, { path: '/', httpOnly: true, sameSite: 'lax', expires: expires ? new Date(expires) : undefined }); console.log(url.searchParams) const redirectTo = url.searchParams.get('redirectTo') || '/' console.log("redirectTo", redirectTo) redirect(303, redirectTo); return { success: true, } } return { success: false, } }}
/routes/login/+page.svelte
<script lang="ts"> import { enhance } from "$app/forms";</script><h1>Login</h1><form method="POST" action="?/login" use:enhance><label>Email<input name="email" type="email" required /></label><label>password<input name="password" type="password" required /></label><button>Log in</button></form>
The output of console.log("url", url)
is missing that URL with redirectTo value.
url URL { href: 'http://localhost:5173/login?/login', origin: 'http://localhost:5173', protocol: 'http:', username: '', password: '', host: 'localhost:5173', hostname: 'localhost', port: '5173', pathname: '/login', search: '?/login', searchParams: URLSearchParams { '/login' => '' }, hash: ''}
What Am I doing wrong? I followed logic from docs.
Solution
I managed to solve this problem.I've used use:enhanced
on Login
form, to pass search param redirectTo
from URL into action.
+page.svelte
for login route
<script lang="ts"> import { enhance } from "$app/forms"; import { page } from "$app/stores"; let currentUrl = $page.url.href; const url: URL = new URL(currentUrl); const redirectTo: string = url.searchParams.get("redirectTo") ?? "";</script><h1>Login</h1><h1>{currentUrl}</h1><h2>{redirectTo}</h2><form method="POST" action="?/login" use:enhance={({ formData }) => { formData.append("redirectTo", redirectTo); }}><label>Email<input name="email" type="email" required /></label><label>password<input name="password" type="password" required /></label><button>Log in</button></form>
+page.server.ts
for login route actions
import { redirect } from '@sveltejs/kit'; export const actions = { login: async ({request, cookies, url}) => { const formData = await request.formData(); const data = { email: formData.get('email'), password: formData.get('password'), redirectTo: formData.get("redirectTo")} console.log("data", data) const response = await fetch("http://localhost:4000/v1/tokens/authentication", { method: 'POST', headers: {'Content-Type': 'application/json' }, body: JSON.stringify({email: data.email, password: data.password}), credentials: 'include' }) if (!response.ok) { console.log('err', response) return {success: false}; } const cookie = response.headers.get('set-cookie'); if (cookie !== null) { const parts = cookie.split(';'); const token = parts[0].split('=')[1]; const expires = parts.find(p => p.trim().startsWith('Expires'))?.split('=')[1]; cookies.set('auth_token', token, { path: '/', httpOnly: true, sameSite: 'lax', expires: expires ? new Date(expires) : undefined }); console.log(url.searchParams) const redirectTo = data.redirectTo != null ? data.redirectTo.toString() : "/" console.log("redirectTo", redirectTo) redirect(303, redirectTo); } return { success: false, } }, register: async (event) => { console.log('elo') } }