UNPKG

kequapp

Version:

DEPRECATED: renamed to @kequtech/arbor

62 lines (61 loc) 2.04 kB
import { Ex } from "../ex.js"; export function createCookies(req, res) { const result = {}; let values; function get(key) { setup(); return values[key]; } function set(key, value, options) { setup(); validateCookieName(key); result[key] = buildAttrs(key, value, options); values[key] = value; res.setHeader('Set-Cookie', Object.values(result)); } function remove(key) { setup(); set(key, '', { maxAge: 0 }); delete values[key]; } function setup() { if (values === undefined) values = parseCookieHeader(req.headers.cookie); } return { get, set, remove }; } function buildAttrs(key, value, options) { const attrs = [`${key}=${encodeURIComponent(value)}`, 'Path=/']; if (options?.domain !== undefined) attrs.push(`Domain=${options.domain}`); if (options?.expires !== undefined) attrs.push(`Expires=${options.expires.toUTCString()}`); if (options?.maxAge !== undefined) attrs.push(`Max-Age=${Math.max(Math.floor(options.maxAge), 0)}`); if (options?.secure === true || options?.sameSite === 'None') attrs.push('Secure'); if (options?.httpOnly) attrs.push('HttpOnly'); if (options?.sameSite !== undefined) attrs.push(`SameSite=${options.sameSite}`); return attrs.join('; '); } function parseCookieHeader(cookie) { const result = {}; if (cookie !== undefined) { for (const part of cookie.split(/; */)) { const i = part.indexOf('='); const key = i >= 0 ? part.slice(0, i).trim() : part.trim(); const value = i >= 0 ? part.slice(i + 1).trim() : ''; if (key) { result[key] = decodeURIComponent(value); } } } return result; } function validateCookieName(name) { if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name)) { throw Ex.InternalServerError(`Cookie name contains invalid characters: ${name}`); } }