dipper/src/lib/api/cookies.ts

84 lines
1.9 KiB
TypeScript

import { PUBLIC_COOKIES_SECURE, PUBLIC_DOMAIN } from '$env/static/public';
import { parseBool } from '$lib/env';
import type { Cookies } from '@sveltejs/kit';
interface CookieInfo {
name: string;
value: string;
options: {
SameSite?: 'Strict' | 'Lax' | 'None';
Secure: boolean;
Partitioned: boolean;
HttpOnly: boolean;
Expires?: Date;
'Max-Age'?: number;
Path?: string;
Domain?: string;
};
}
function parseCookieHeader(headerValue: string): CookieInfo {
const [nv, ...options] = headerValue.split(';');
const [name, value] = nv.split('=').map((v) => v.trim());
const cookie: CookieInfo = {
name,
value,
options: {
Secure: false,
Partitioned: false,
HttpOnly: false
}
};
options.forEach((option) => {
const [key, value] = option.split('=').map((v) => v.trim());
switch (key) {
case 'Secure':
cookie.options.Secure = true;
break;
case 'SameSite':
cookie.options.SameSite = value as 'Strict' | 'Lax' | 'None';
break;
case 'Partitioned':
cookie.options.Partitioned = true;
break;
case 'HttpOnly':
cookie.options.HttpOnly = true;
break;
case 'Expires':
cookie.options.Expires = new Date(value);
break;
case 'Max-Age':
cookie.options['Max-Age'] = parseInt(value, 10);
break;
case 'Path':
cookie.options.Path = value;
break;
case 'Domain':
cookie.options.Domain = value;
break;
}
});
return cookie;
}
export function passthroughSession(response: Response, cookies: Cookies) {
if (response.ok) {
const cookieHeader = response.headers.get('Set-Cookie');
if (!cookieHeader) {
return;
}
const info = parseCookieHeader(cookieHeader);
cookies.set(info.name, info.value, {
httpOnly: info.options.HttpOnly,
secure: parseBool(PUBLIC_COOKIES_SECURE),
sameSite: 'strict',
domain: PUBLIC_DOMAIN,
expires: info.options.Expires,
maxAge: info.options['Max-Age'],
path: info.options.Path ?? '/'
});
}
}