Registry / http-networking / http-cache-semantics

http-cache-semantics

JSON →
library4.2.0jsnpmunverified

This library provides a robust implementation of HTTP caching logic as defined by RFC 7234/9111 (for user agents and shared caches) and RFC 5861 (for `stale-if-error` and `stale-while-revalidate`). It allows developers to determine the cacheability of HTTP responses and whether a stored response can satisfy a new request, taking into account complex factors like the `Vary` header, proxy revalidation, and authenticated responses. The current stable version is 4.2.0. The library helps in building correct HTTP caches and proxies by abstracting away the intricacies of cache control directives, providing methods like `storable()` to check if a response can be cached, and `satisfiesWithoutRevalidation()` to validate if a cached entry is suitable for a subsequent request. It offers fine-grained control via constructor options like `shared`, `cacheHeuristic`, and `immutableMinTimeToLive`.

npm install http-cache-semantics
INSTALL
IMPORT
SIG · HTTP-CACHE-SEMANTI
H
http-cache-semantics
http-networkingjavascriptv4.2.0
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

CachePolicy
import { CachePolicy } from 'http-cache-semantics';
const CachePolicy = require('http-cache-semantics').CachePolicy;
Main class for evaluating HTTP cache policy. The library ships with TypeScript types and supports both ESM and CommonJS.
CachePolicyOptions
import type { CachePolicyOptions } from 'http-cache-semantics';
TypeScript type for the constructor options of CachePolicy, useful for type-checking.
CachePolicy
import { CachePolicy } from 'http-cache-semantics';
import CachePolicy from 'http-cache-semantics';
CachePolicy is a named export, not a default export. Incorrectly using a default import will result in a TypeError.

Demonstrates the basic workflow of `http-cache-semantics`: creating a `CachePolicy` from an initial request/response, checking its storability, caching it, and then using `satisfiesWithoutRevalidation()` to determine if a subsequent request can be served from the cache, respecting `Vary` headers and other HTTP rules.

import { CachePolicy } from 'http-cache-semantics'; // Simulate an initial request and its corresponding response const initialRequest = { url: 'https://api.example.com/data/items', method: 'GET', headers: { 'accept': 'application/json', 'authorization': 'Bearer mysecrettoken' }, }; const initialResponse = { status: 200, headers: { 'cache-control': 'public, max-age=3600, s-maxage=600', 'content-type': 'application/json', 'vary': 'Accept, Authorization', // Note: Library expects lowercase, but here we simulate a common server response 'date': new Date().toUTCString(), }, body: '{"id": 1, "name": "Cached Item"}', }; // Options for the cache policy evaluation const options = { shared: true, // Evaluate from a shared cache perspective (e.g., a proxy) cacheHeuristic: 0.1, // 10% of response's age as fallback TTL immutableMinTimeToLive: 24 * 3600 * 1000, // 24 hours for 'immutable' }; // --- Step 1: Create and store the cache policy for an incoming response --- // Ensure headers are lowercase before passing to CachePolicy const lowercaseInitialRequest = { ...initialRequest, headers: Object.fromEntries(Object.entries(initialRequest.headers).map(([k, v]) => [k.toLowerCase(), v])) }; const lowercaseInitialResponse = { ...initialResponse, headers: Object.fromEntries(Object.entries(initialResponse.headers).map(([k, v]) => [k.toLowerCase(), v])) }; const policy = new CachePolicy(lowercaseInitialRequest, lowercaseInitialResponse, options); if (!policy.storable()) { console.log("Initial response is not storable in the cache. Discarding."); } else { const letsPretendThisIsSomeCache = new Map<string, { policy: CachePolicy, body: string }>(); const timeToLive = policy.timeToLive(); console.log(`Response is storable. Estimated time to live: ${timeToLive}ms`); // Store the policy object along with the response body letsPretendThisIsSomeCache.set(initialRequest.url, { policy, body: initialResponse.body }); // --- Step 2: Later, an identical new request comes in --- const newRequest = { url: 'https://api.example.com/data/items', method: 'GET', headers: { 'accept': 'application/json', 'authorization': 'Bearer mysecrettoken' }, }; const cachedEntry = letsPretendThisIsSomeCache.get(newRequest.url); if (cachedEntry) { // Ensure headers are lowercase for the new request too const lowercaseNewRequest = { ...newRequest, headers: Object.fromEntries(Object.entries(newRequest.headers).map(([k, v]) => [k.toLowerCase(), v])) }; if (cachedEntry.policy.satisfiesWithoutRevalidation(lowercaseNewRequest)) { // The cached response is valid for the new request without revalidation const responseHeaders = cachedEntry.policy.responseHeaders(); console.log("Cached response can be used without revalidation."); console.log("Updated response headers for client (includes Age, removes private headers):", responseHeaders); // In a real application, you would send { headers: responseHeaders, body: cachedEntry.body } to the client. } else { console.log("Cache hit, but revalidation is required or response is not suitable for this new request."); // Implement revalidation logic using policy.revalidationHeaders() and policy.revalidatedPolicy() } } else { console.log("Cache miss. No entry found for this URL."); // Fetch fresh data } }
Debug
Known issues
gotchaAll request and response header names passed to `CachePolicy` must be provided in lowercase. Failing to do so will result in incorrect caching behavior, as the library expects standardized header processing.
fix
Ensure all header keys in your request and response objects are converted to lowercase before passing them to the CachePolicy constructor, e.g., `{'Content-Type': '...'}` should be `{'content-type': '...'}`.
affects: >=1.0
gotchaMisunderstanding the `shared` option can lead to incorrect cacheability decisions. If `options.shared` is `true` (the default), `private` responses are not cacheable, and `s-maxage` takes precedence. If `false`, then `private` is cacheable, and `s-maxage` is ignored. This is critical for distinguishing between shared proxies and single-user caches.
fix
Explicitly set `shared: true` for HTTP clients (like proxies) and `shared: false` for single-user browser-like caches, based on your application's caching context and intended behavior.
affects: >=1.0
gotchaThe `storable()` method only indicates if a response *can* be stored in the cache. To determine if a *cached* response can satisfy a *new* request, you *must* use `satisfiesWithoutRevalidation(newRequest)`. This method accounts for `Vary` headers, request-specific cache directives, and other critical HTTP rules.
fix
Always use `policy.satisfiesWithoutRevalidation(newRequest)` to check if a cached response is valid for an incoming request. Only rely on `policy.storable()` for initial cache-eligibility checks.
affects: >=1.0
gotchaImproper handling of the `Vary` header is a common cause of incorrect caching. `http-cache-semantics` automatically considers `Vary` in `satisfiesWithoutRevalidation()`, but developers must be aware that a cached response might not be valid if the `Vary` header fields on the new request do not match the original cached request's headers.
fix
Ensure your cache key for `Vary`-dependent responses is sufficiently granular, or rely on `satisfiesWithoutRevalidation()` to perform the necessary checks. The library handles `Vary` internally, but client-side logic should respect its implications.
affects: >=1.0
gotchaUsing `ignoreCargoCult: true` can override common anti-cache directives (like `pre-check` and `post-check`) if non-standard directives are present. While useful for problematic origins, indiscriminately enabling this option might lead to over-caching of responses intended to be fresh.
fix
Only enable `ignoreCargoCult: true` when explicitly dealing with servers known to send misleading or anti-pattern `Cache-Control` directives, and after careful consideration of caching implications.
affects: >=1.0
Errors
Common errors & fixes
TypeError: Cannot read properties of undefined (reading 'headers')
The `request` or `response` object passed to the `CachePolicy` constructor is missing the `headers` property, or it is `null`/`undefined`.
fix
Ensure both `request` and `response` objects always include a `headers` property, even if it's an empty object (`{}`), before being used to instantiate `CachePolicy`.
Cached response not served, even though 'Cache-Control: max-age' indicates it should be fresh.
The cached response has a `Vary` header, and the headers of the new request do not match those of the original request used to create the cache entry, or the new request contains restrictive cache control directives (e.g., `Cache-Control: no-cache`).
fix
Always use `policy.satisfiesWithoutRevalidation(newRequest)` to check if a cached response can be validly served for a new request. This method correctly evaluates `Vary` headers and other request-specific conditions, which simple freshness checks like `timeToLive()` do not.
Incorrect caching of `private` or `s-maxage` responses in a shared/single-user context.
The `shared` option in the `CachePolicy` constructor is not correctly configured for the caching environment (e.g., `shared: false` for a proxy, or `shared: true` for a single-user cache leading to private data exposure).
fix
Set `options.shared: true` (the default) for shared caches (e.g., HTTP proxies) to respect `s-maxage` and treat `private` as non-cacheable. Set `options.shared: false` for single-user caches (e.g., browser-like caches) to ignore `s-maxage` and allow caching of `private` responses.
Upgrade
Version history
4.2.0latest on npm
Audit
Dependencies

No dependency data recorded yet.

Agent activity
6 hits · last 30 days
node
6
Resources