UNPKG

fexios

Version:

Fetch based HTTP client with similar API to axios for browser and Node.js

1 lines 18.6 kB
{"version":3,"file":"index.mjs","sources":["../../src/plugins/cookie-jar/CookieJar.ts","../../src/plugins/cookie-jar/index.ts"],"sourcesContent":["/**\n * Cookie object interface\n */\nexport interface CookieJarItem {\n name: string\n value: string\n domain?: string\n path?: string\n expires?: Date\n maxAge?: number\n secure?: boolean\n httpOnly?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n // Internal field to track creation time when maxAge is set\n _createdAt?: Date\n // Internal: host-only cookie flag (no Domain attribute provided by server)\n _hostOnly?: boolean\n}\n\n/**\n * Cookie Jar\n *\n * @author dragon-fish <dragon-fish@qq.com>\n * @license MIT\n */\nexport class CookieJar {\n private cookies: Map<string, CookieJarItem> = new Map()\n\n /**\n * Set a cookie\n */\n setCookie(cookie: CookieJarItem, domain?: string, path?: string): void {\n const effectiveDomain = cookie.domain ?? domain\n const effectivePath = cookie.path ?? path ?? '/'\n const hostOnly = cookie.domain === undefined && domain !== undefined\n\n const key = this.getCookieKey(cookie.name, effectiveDomain, effectivePath)\n\n // Set creation time if maxAge is provided\n const cookieWithTime = {\n ...cookie,\n domain: effectiveDomain,\n path: effectivePath,\n _hostOnly: cookie._hostOnly ?? hostOnly,\n _createdAt: cookie.maxAge !== undefined ? new Date() : cookie._createdAt,\n }\n\n this.cookies.set(key, cookieWithTime)\n }\n\n /**\n * Get a cookie\n */\n getCookie(\n name: string,\n domain?: string,\n path?: string\n ): CookieJarItem | undefined {\n // Try exact match first\n const exactKey = this.getCookieKey(name, domain, path)\n let cookie = this.cookies.get(exactKey)\n\n if (cookie && !this.isCookieExpired(cookie)) {\n return cookie\n }\n\n // If not found, try fuzzy match\n for (const storedCookie of this.cookies.values()) {\n if (\n storedCookie.name === name &&\n this.isCookieMatch(storedCookie, domain, path) &&\n !this.isCookieExpired(storedCookie)\n ) {\n return storedCookie\n }\n }\n\n return undefined\n }\n\n /**\n * Get all matching cookies\n */\n getCookies(domain?: string, path?: string): CookieJarItem[] {\n const result: CookieJarItem[] = []\n\n for (const cookie of this.cookies.values()) {\n if (\n this.isCookieMatch(cookie, domain, path) &&\n !this.isCookieExpired(cookie)\n ) {\n result.push(cookie)\n }\n }\n\n return result\n }\n\n /**\n * Delete a cookie\n */\n deleteCookie(name: string, domain?: string, path?: string): boolean {\n const key = this.getCookieKey(name, domain, path)\n return this.cookies.delete(key)\n }\n\n /**\n * Clear all cookies\n */\n clear(): void {\n this.cookies.clear()\n }\n\n /**\n * Clean expired cookies\n */\n cleanExpiredCookies(): number {\n let cleanedCount = 0\n const now = new Date()\n\n for (const [key, cookie] of this.cookies.entries()) {\n if (this.isCookieExpired(cookie)) {\n this.cookies.delete(key)\n cleanedCount++\n }\n }\n\n return cleanedCount\n }\n\n /**\n * Get all cookies (including expired ones)\n */\n getAllCookies(domain?: string, path?: string): CookieJarItem[] {\n const result: CookieJarItem[] = []\n\n for (const cookie of this.cookies.values()) {\n if (this.isCookieMatch(cookie, domain, path)) {\n result.push(cookie)\n }\n }\n\n return result\n }\n\n /**\n * Parse cookies from Set-Cookie header\n */\n parseSetCookieHeader(\n setCookieHeader: string,\n domain?: string,\n path?: string\n ): void {\n const cookieStrings = this.splitSetCookieHeader(setCookieHeader)\n\n for (const cookieStr of cookieStrings) {\n const cookie = this.parseCookieString(cookieStr)\n if (cookie) {\n this.setCookie(cookie, domain, path)\n }\n }\n }\n\n /**\n * Generate Cookie header string\n */\n getCookieHeader(domain?: string, path?: string): string {\n const cookies = this.getCookies(domain, path)\n return cookies\n .filter((cookie) => !this.isCookieExpired(cookie))\n .map((cookie) => `${cookie.name}=${cookie.value}`)\n .join('; ')\n }\n\n /**\n * Get the unique key for a cookie\n */\n private getCookieKey(name: string, domain?: string, path?: string): string {\n return `${name}:${domain || '*'}:${path || '/'}`\n }\n\n /**\n * Check if cookie matches the given domain and path\n */\n private isCookieMatch(\n cookie: CookieJarItem,\n domain?: string,\n path?: string\n ): boolean {\n if (domain) {\n if (cookie.domain) {\n if (cookie._hostOnly) {\n if (cookie.domain !== domain) return false\n } else {\n if (!this.isDomainMatch(cookie.domain, domain)) return false\n }\n } else {\n return false\n }\n }\n\n if (path && cookie.path && !this.isPathMatch(cookie.path, path)) {\n return false\n }\n\n return true\n }\n\n /**\n * Check if domain matches\n */\n private isDomainMatch(cookieDomain: string, requestDomain: string): boolean {\n // Ignore leading dot for comparison per RFC 6265\n const cd = cookieDomain.startsWith('.')\n ? cookieDomain.substring(1)\n : cookieDomain\n if (requestDomain === cd) {\n return true\n }\n // Allow subdomain match when Domain attribute is present (non host-only)\n return requestDomain.endsWith('.' + cd)\n }\n\n /**\n * Check if path matches\n */\n private isPathMatch(cookiePath: string, requestPath: string): boolean {\n if (cookiePath === requestPath) {\n return true\n }\n\n if (requestPath.startsWith(cookiePath)) {\n return cookiePath.endsWith('/') || requestPath[cookiePath.length] === '/'\n }\n\n return false\n }\n\n /**\n * Check if cookie is expired\n */\n private isCookieExpired(cookie: CookieJarItem): boolean {\n const now = new Date()\n\n // Check expires attribute\n if (cookie.expires) {\n return now > cookie.expires\n }\n\n // Check maxAge expiration time\n if (cookie.maxAge !== undefined && cookie._createdAt) {\n const expirationTime = new Date(\n cookie._createdAt.getTime() + cookie.maxAge * 1000\n )\n return now > expirationTime\n }\n\n return false\n }\n\n /**\n * Parse cookie string\n */\n private parseCookieString(cookieStr: string): CookieJarItem | null {\n const parts = cookieStr.split(';').map((part) => part.trim())\n if (parts.length === 0) return null\n\n const [nameValue] = parts\n const equalIndex = nameValue.indexOf('=')\n if (equalIndex === -1) return null\n\n const name = nameValue.substring(0, equalIndex).trim()\n const value = nameValue.substring(equalIndex + 1).trim()\n\n const cookie: CookieJarItem = { name, value }\n\n for (let i = 1; i < parts.length; i++) {\n const part = parts[i]\n const equalIndex = part.indexOf('=')\n\n if (equalIndex === -1) {\n // Attributes without value\n const attr = part.toLowerCase()\n if (attr === 'secure') {\n cookie.secure = true\n } else if (attr === 'httponly') {\n cookie.httpOnly = true\n }\n } else {\n const attrName = part.substring(0, equalIndex).trim().toLowerCase()\n const attrValue = part.substring(equalIndex + 1).trim()\n\n switch (attrName) {\n case 'domain':\n cookie.domain = attrValue\n break\n case 'path':\n cookie.path = attrValue\n break\n case 'expires':\n cookie.expires = new Date(attrValue)\n break\n case 'max-age':\n cookie.maxAge = parseInt(attrValue, 10)\n break\n case 'samesite':\n cookie.sameSite = attrValue as 'Strict' | 'Lax' | 'None'\n break\n }\n }\n }\n\n return cookie\n }\n\n /**\n * Safely split a possibly-combined Set-Cookie header string into individual cookie strings.\n * Split on commas that are followed by the start of a new cookie-pair (name=),\n * avoiding commas inside Expires attribute values.\n */\n private splitSetCookieHeader(header: string): string[] {\n if (!header) return []\n const parts = header.split(/,(?=\\s*[^;=]+=)/)\n return parts.map((p) => p.trim()).filter((p) => p.length > 0)\n }\n}\n","import { FexiosPlugin } from '@/index.js'\nimport { CookieJar } from './CookieJar.js'\n\nexport * from './CookieJar.js'\n\ndeclare module '@/index.js' {\n interface Fexios {\n cookieJar?: CookieJar\n }\n}\n\nexport const pluginCookieJar: FexiosPlugin = {\n name: 'fexios-plugin-cookie-jar',\n install(app) {\n const cookieJar = new CookieJar()\n\n // Request interceptor: add cookies to request headers\n app.interceptors.request.use((ctx) => {\n const url = new URL(ctx.url!)\n const cookieHeader = cookieJar.getCookieHeader(url.hostname, url.pathname)\n\n if (cookieHeader) {\n ctx.headers = {\n ...ctx.headers,\n Cookie: cookieHeader,\n }\n }\n\n return ctx\n })\n\n // Response interceptor: parse Set-Cookie header\n app.interceptors.response.use((ctx) => {\n const url = new URL(ctx.url!)\n const headersAny = ctx.rawResponse?.headers as any\n const host = url.hostname\n const reqPath = url.pathname\n\n // Prefer undici's getSetCookie() when available\n const getSetCookie =\n typeof headersAny?.getSetCookie === 'function'\n ? headersAny.getSetCookie.bind(headersAny)\n : undefined\n\n if (getSetCookie) {\n const list: string[] = getSetCookie()\n if (Array.isArray(list) && list.length > 0) {\n for (const sc of list) {\n cookieJar.parseSetCookieHeader(sc, host, reqPath)\n }\n }\n } else {\n const setCookieHeader = ctx.rawResponse?.headers?.get('set-cookie')\n if (setCookieHeader) {\n cookieJar.parseSetCookieHeader(setCookieHeader, host, reqPath)\n }\n }\n\n return ctx\n })\n\n // Expose cookieJar instance on app for external access\n app.cookieJar = cookieJar\n\n return app\n },\n}\n"],"names":["equalIndex"],"mappings":"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"}