import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit'; import { paraglideMiddleware } from '$lib/paraglide/server'; import { sequence } from '@sveltejs/kit/hooks'; import { env } from 'process'; import { cookieName, cookieMaxAge, locales } from '$lib/paraglide/runtime'; const PUBLIC_PATHS = ['/login', '/logout']; function detectLocale(acceptLanguage: string): string | null { const preferred = acceptLanguage .split(',') .map((part) => { const [lang, q] = part.trim().split(';q='); return { lang: lang.trim().split('-')[0].toLowerCase(), q: q ? parseFloat(q) : 1 }; }) .sort((a, b) => b.q - a.q); for (const { lang } of preferred) { if ((locales as readonly string[]).includes(lang)) return lang; } return null; } const handleLocaleDetection: Handle = ({ event, resolve }) => { if (!event.cookies.get(cookieName)) { const locale = detectLocale(event.request.headers.get('accept-language') ?? ''); if (locale) { event.cookies.set(cookieName, locale, { path: '/', sameSite: 'lax', maxAge: cookieMaxAge }); } } return resolve(event); }; const handleAuth: Handle = async ({ event, resolve }) => { const isPublic = PUBLIC_PATHS.some((p) => event.url.pathname.startsWith(p)); if (!isPublic && !event.locals.user) { throw redirect(302, '/login'); } return resolve(event); }; const handleParaglide: Handle = ({ event, resolve }) => paraglideMiddleware(event.request, ({ request, locale }) => { event.request = request; return resolve(event, { transformPageChunk: ({ html }) => html.replace('%paraglide.lang%', locale) }); }); const userGroup: Handle = async ({ event, resolve }) => { const auth = event.cookies.get('auth_token'); if (auth) { try { const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080'; const response = await fetch(`${apiUrl}/api/users/me`, { headers: { Authorization: auth } }); if (response.ok) { const user = await response.json(); event.locals.user = user; } } catch (error) { console.error('Error fetching user in hook:', error); } } return resolve(event); }; export const handleFetch: HandleFetch = async ({ event, request, fetch }) => { const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080'; const isApi = request.url.startsWith(apiUrl) || request.url.includes('/api/'); const isNotLoginTest = !request.url.includes('/api/users/me'); if (isApi && isNotLoginTest) { const token = event.cookies.get('auth_token'); if (!token) { return new Response('Unauthorized', { status: 401 }); } // Clone the request first to preserve the body const clonedRequest = request.clone(); // Create new request with Authorization header and preserved body const modifiedRequest = new Request(clonedRequest, { headers: { ...Object.fromEntries(clonedRequest.headers), 'Authorization': token } }); return fetch(modifiedRequest); } return fetch(request); }; export const handle = sequence(userGroup, handleAuth, handleLocaleDetection, handleParaglide);