import { $ } from "@builder.io/qwik"; import type { RequestEventAction } from "@builder.io/qwik-city"; import { server$ } from "@builder.io/qwik-city"; interface CookieOption { [key: string]: string; } interface Cookie { name: string | undefined; value: string | undefined; options: CookieOption[] | undefined; } export const parseCookies = $((setCookieHeader: string): Cookie[] => { const rawCookieStrings = setCookieHeader.split(/,(?=\s[a-zA-Z]+=)/); const parsedCookies: Cookie[] = rawCookieStrings.map((cookieString) => { const cookieComponents = cookieString.split(";"); const rawNameAndValue = cookieComponents.shift(); if (rawNameAndValue) { const nameAndValue = rawNameAndValue.split("="); const cookieName = nameAndValue.shift()?.trim(); const cookieValue = nameAndValue.shift()?.trim(); if (cookieName && cookieValue) { const cookieOptions: CookieOption[] = cookieComponents.map( (optionString) => { const optionComponents = optionString.split("="); const optionName = optionComponents.shift()?.trim(); const optionValue = optionComponents.shift()?.trim(); if (optionName && optionValue) { return { [optionName]: optionValue }; } else { return {}; } }, ); return { name: cookieName, value: cookieValue, options: cookieOptions }; } } return { name: undefined, value: undefined, options: undefined }; }); return parsedCookies; }); export const sendPost = server$( async ( url: string, path: string, data: any, includeCookies: string[], event: RequestEventAction, ) => { const cookies = includeCookies.reduce((acc, curr) => { const cookie = event.cookie.get(curr)?.value; if (cookie) { acc[curr] = cookie; } return acc; }, {} as any); const joinCookies = Object.entries(cookies) .map(([key, value]) => `${key}=${value}`) .join("; "); const request = await fetch(url + path, { method: "POST", headers: { Cookie: joinCookies, "Content-Type": "application/json", }, body: JSON.stringify(data), credentials: "include", }); const setCookies = await parseCookies( request.headers.get("set-cookie") || "", ); setCookies.forEach((c) => { if (c.name && c.value) { const e = c.options ? c.options.find((o) => "Expires" in o) : null; if (c.name && c.value) { event.cookie.set(c.name, c.value, { expires: e && e.Expires ? new Date(e.Expires) : undefined, httpOnly: true, path: "/", sameSite: "strict", secure: false, }); } } }); return await request.json(); }, ); export const PostRequest = server$( async (path: string, data: any, event: RequestEventAction) => { return await sendPost( "http://localhost:3000", path, data, ["session"], event, ); }, );