TL;DR:
Caution to users using the +hooks.server.ts Handle function!
Notice that response.headers.set('set-cookie', ... discards the flash message cookie.
It is imperative that instead response.headers.append('set-cookie', ... must be used.
Multiple set-cookie headers are supported.
I propose adding a documentation specifically warning adventurous users from overwriting the cookie.
I have had a bit of trouble getting flash messages to work.
In the +layout.server.tsServerLoad I print the cookies before the flash wrapper is executed:
import type { ServerLoad } from '@sveltejs/kit';
import { loadFlash } from 'sveltekit-flash-message/server';
import type { LayoutServerData } from './$types';
export const load: ServerLoad = (event) => {
console.log('ServerLoad cookies', event.request.headers.get('cookie'));
return loadFlash(async ({ locals }) => {
return {
user: locals.user,
categories: locals.categories,
} satisfies LayoutServerData;
})(event);
};
In the +layout.svelte I render the flash
<script lang="ts">
import { showFlash } from '$lib/Toast/toast.client';
showFlash(page);
</script>
Show flash reactively prints client cookies
import type { Page } from '@sveltejs/kit';
import type { Readable } from 'svelte/motion';
import { getFlash } from 'sveltekit-flash-message/client';
import { toast } from './toast';
export function showFlash(page: Readable<Page<Record<string, string>, string | null>>) {
page.subscribe((page) => {
console.log('page: ', page.data.flash);
});
const flash = getFlash(page);
flash.subscribe((msg) => {
console.log('getFlash: ', msg);
if (msg) {
toast.show(msg);
}
flash.set(undefined);
});
}
In my login form `+page.server.ts I show a toast upon failed login
import type { Actions } from './$types';
import { loginSchema, sanitizeLoginForm } from './schema';
import { ZodError } from 'zod';
import { createRedirectTo, ensureRootPath } from '$lib/url';
import type { ToastMessage } from '$lib/Toast/toast';
import { redirect, setFlash } from 'sveltekit-flash-message/server';
export const actions: Actions = {
default: async (event) => {
const { locals, request, url } = event;
const formData = Object.fromEntries(await request.formData());
// redacted for brevety. Below the login failed
setFlash(
{
type: 'surface',
message: ['Lost your password?', { name: 'Reset it here', url: `/auth/reset-password?redirectTo=${createRedirectTo(url)}` }],
} satisfies ToastMessage,
event
);
console.log('setFlash: ', event.cookies.get('flash'));
return {
data: sanitizeLoginForm(formData),
errors: {
nameOrEmail: ['Invalid username or password'],
password: ['Invalid username or password'],
},
};
Interacting with the form should yield the following debug output:
server: setFlash: {"type":"surface","message":["Lost your password?",{"name":"Reset it here","url":"/auth/reset-password?redirectTo=/"}]}
server: ServerLoad cookies: flash=%7B%22type%22:%22surface%22,%22message%22:%5B%22Lost%20your%20password?%22,%7B%22name%22:%22Reset%20it%20here%22,%22url%22:%22/auth/reset-password?redirectTo=/%22%7D%5D%7D
client: page: {"type":"surface","message":["Lost your password?",{"name":"Reset it here","url":"/auth/reset-password?redirectTo=/"}]}
client: getFlash: {"type":"surface","message":["Lost your password?",{"name":"Reset it here","url":"/auth/reset-password?redirectTo=/"}]}
...but the server sided cookie is lost during the redirect, so the store is never updated, and the toast does not arrive at the client side.
server: setFlash: {"type":"surface","message":["Lost your password?",{"name":"Reset it here","url":"/auth/reset-password?redirectTo=/"}]}
server: ServerLoad cookies: null
client: page: undefined
I traced this issue back to my bogus authentication implementation hook:
Notice that response.headers.set('set-cookie', ... discards the flash message cookie.
It is imperative that instead response.headers.append('set-cookie', ... must be used.
Multiple set-cookie headers are supported.
I propose adding a documentation specifically warning adventurous users from overwriting the cookie.
TL;DR: Caution to users using the
+hooks.server.ts
Handle function!I have had a bit of trouble getting flash messages to work. In the
+layout.server.ts
ServerLoad
I print the cookies before the flash wrapper is executed:In the
+layout.svelte
I render the flashShow flash reactively prints client cookies
In my login form `+page.server.ts I show a toast upon failed login
Interacting with the form should yield the following debug output:
...but the server sided cookie is lost during the redirect, so the store is never updated, and the toast does not arrive at the client side.
I traced this issue back to my bogus authentication implementation hook:
Notice that
response.headers.set('set-cookie', ...
discards the flash message cookie. It is imperative that insteadresponse.headers.append('set-cookie', ...
must be used. Multipleset-cookie
headers are supported.I propose adding a documentation specifically warning adventurous users from overwriting the cookie.