UNPKG

@push.rocks/webrequest

Version:

Modern, fetch-compatible web request library with intelligent HTTP caching, retry strategies, and fault tolerance.

145 lines 8.98 kB
/** * HTTP Cache Header parsing and utilities * Implements RFC 7234 (HTTP Caching) */ /** * Parse Cache-Control header into metadata */ export function parseCacheControl(cacheControlHeader) { const metadata = { maxAge: 0, immutable: false, noCache: false, noStore: false, mustRevalidate: false, }; if (!cacheControlHeader) { return metadata; } const directives = cacheControlHeader .toLowerCase() .split(',') .map((d) => d.trim()); for (const directive of directives) { if (directive === 'no-cache') { metadata.noCache = true; } else if (directive === 'no-store') { metadata.noStore = true; } else if (directive === 'immutable') { metadata.immutable = true; } else if (directive === 'must-revalidate') { metadata.mustRevalidate = true; } else if (directive.startsWith('max-age=')) { const maxAge = parseInt(directive.split('=')[1], 10); if (!isNaN(maxAge)) { metadata.maxAge = maxAge * 1000; // Convert to milliseconds } } } return metadata; } /** * Parse Expires header into timestamp */ export function parseExpires(expiresHeader) { if (!expiresHeader) { return undefined; } try { const date = new Date(expiresHeader); return date.getTime(); } catch { return undefined; } } /** * Extract cache metadata from response headers */ export function extractCacheMetadata(headers) { const cacheControl = headers.get('cache-control'); const expires = headers.get('expires'); const etag = headers.get('etag'); const lastModified = headers.get('last-modified'); const metadata = parseCacheControl(cacheControl); // If no max-age from Cache-Control, try Expires header if (metadata.maxAge === 0 && expires) { const expiresTime = parseExpires(expires); if (expiresTime) { metadata.maxAge = Math.max(0, expiresTime - Date.now()); } } return { maxAge: metadata.maxAge || 0, etag: etag || undefined, lastModified: lastModified || undefined, immutable: metadata.immutable || false, noCache: metadata.noCache || false, noStore: metadata.noStore || false, mustRevalidate: metadata.mustRevalidate || false, }; } /** * Check if a cached response is still fresh */ export function isFresh(cacheEntry, metadata) { // no-store means never cache if (metadata.noStore) { return false; } // If immutable, it's always fresh if (metadata.immutable) { return true; } const age = Date.now() - cacheEntry.timestamp; const maxAge = cacheEntry.maxAge || metadata.maxAge || 0; // If no max-age specified, consider stale if (maxAge === 0) { return false; } return age < maxAge; } /** * Check if revalidation is required */ export function requiresRevalidation(metadata) { return metadata.noCache || metadata.mustRevalidate; } /** * Create conditional request headers for revalidation */ export function createConditionalHeaders(cacheEntry) { const headers = {}; if (cacheEntry.etag) { headers['if-none-match'] = cacheEntry.etag; } if (cacheEntry.lastModified) { headers['if-modified-since'] = cacheEntry.lastModified; } return headers; } /** * Convert Headers object to plain object for storage */ export function headersToObject(headers) { const obj = {}; headers.forEach((value, key) => { obj[key] = value; }); return obj; } /** * Convert plain object back to Headers */ export function objectToHeaders(obj) { const headers = new Headers(); Object.entries(obj).forEach(([key, value]) => { headers.set(key, value); }); return headers; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuaGVhZGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NhY2hlL2NhY2hlLmhlYWRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBSUg7O0dBRUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLGtCQUFpQztJQUVqQyxNQUFNLFFBQVEsR0FBNEI7UUFDeEMsTUFBTSxFQUFFLENBQUM7UUFDVCxTQUFTLEVBQUUsS0FBSztRQUNoQixPQUFPLEVBQUUsS0FBSztRQUNkLE9BQU8sRUFBRSxLQUFLO1FBQ2QsY0FBYyxFQUFFLEtBQUs7S0FDdEIsQ0FBQztJQUVGLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ3hCLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxrQkFBa0I7U0FDbEMsV0FBVyxFQUFFO1NBQ2IsS0FBSyxDQUFDLEdBQUcsQ0FBQztTQUNWLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFeEIsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNuQyxJQUFJLFNBQVMsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUM3QixRQUFRLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUMxQixDQUFDO2FBQU0sSUFBSSxTQUFTLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDcEMsUUFBUSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDMUIsQ0FBQzthQUFNLElBQUksU0FBUyxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ3JDLFFBQVEsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQzVCLENBQUM7YUFBTSxJQUFJLFNBQVMsS0FBSyxpQkFBaUIsRUFBRSxDQUFDO1lBQzNDLFFBQVEsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO1FBQ2pDLENBQUM7YUFBTSxJQUFJ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