Http Client Cache
RFC 9111 outbound HTTP cache for b.httpClient.request. Stores GET/HEAD responses keyed on (URL, method, sorted Vary-header values), honours Cache-Control directives (no-store, no-cache, private, max-age, s-maxage, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate, stale-if-error), legacy Pragma: no-cache and Expires, computes freshness per RFC 9111 §4.2 (heuristic 10% rule when no explicit lifetime), revalidates with If-None-Match / If-Modified-Since and merges 304 headers into the stored entry (RFC 9111 §5).
Two store backends ship in-the-box: memoryStore (bounded LRU, per-byte and per-entry caps, eviction emits an audit event) and the explicit Store interface (get / set / delete / clear) so operators can wire their own — Redis, filesystem, etc. The memory store handles the common single-process case without pulling in an external dependency. Operators with shared-cache semantics across a fleet wire their own Store against a shared backing service.
Composes through b.httpClient.request({ ..., cache }). Without opts.cache, behaviour is unchanged — zero overhead for callers who don't want caching. Failures inside the cache hot path (store throws, malformed entry, revalidation network error outside stale-if-error) drop silent and the request falls back to the network — caching is never allowed to surface as a request failure. The same audit / observability hooks emit on every cache decision (hit / miss / stale / revalidated / evicted) so operators get end-to-end visibility.
b.httpClient.cache.memoryStore(opts) #
{
maxBytes: number, // total stored body bytes; default: 64 MiB
maxEntries: number, // count cap; default: 1024
evictionPolicy: "lru", // currently the only policy; reserved
}
In-memory bounded-LRU cache store implementing the Store shape: get(key), set(key, entry), delete(key), clear(). Eviction runs when the byte total or entry count exceeds the configured caps; eviction emits an audit event when an audit sink is wired (via b.httpClient.cache.create({ audit })). Stored values include the response body buffer, so the byte total reflects real memory pressure rather than a rough estimate.
Suitable for single-process workloads. For shared-cache semantics across a fleet, wire your own Store against a shared backing service (Redis, filesystem, etc.) — the same shape applies.
var store = b.httpClient.cache.memoryStore({
maxBytes: 16 * 1024 * 1024,
maxEntries: 256,
});
var cache = b.httpClient.cache.create({ store: store });
await b.httpClient.request({ url: "https://example.com/", cache: cache });
b.httpClient.cache.create(opts) #
{
store: , // Store: { get, set, delete, clear }
sharedCache: true, // honour s-maxage; refuse Cache-Control: private
defaultMaxStale: 0, // seconds — serve stale up to this far past expiry
revalidateInBackground: true, // s-w-r kicks off background revalidation
audit: undefined, // audit sink with safeEmit({...})
observability: undefined, // optional { event, safeEvent }
statusHeader: "x-blamejs-cache", // response header carrying the cache decision; null/false to suppress, or a custom name (e.g. "x-cache")
}
Builds an RFC 9111 cache instance for b.httpClient.request. The returned object plugs into a request via opts.cache. Without opts.cache, the request path is unchanged — no overhead for non-caching callers. The cache evaluates each response per RFC 9111 §3 (storage decision: method / status / Cache-Control / Vary), tracks freshness per §4.2 (s-maxage > max-age > Expires > heuristic 10% of (Date - Last-Modified) capped at 24h), revalidates conditionally per §4.3 (If-None-Match / If-Modified-Since), and merges 304 headers per §5.
sharedCache: true (default) honours s-maxage over max-age and refuses to store responses with Cache-Control: private — operator services share a cache with each other, so a per-user private response must not leak across users via the cache. Single-tenant scripts pass sharedCache: false to behave as a private cache.
defaultMaxStale lets the cache return a stored entry past its freshness lifetime (within the configured number of seconds) even without an explicit upstream stale-while-revalidate / stale-if-error. Default 0 — operators opt in.
revalidateInBackground (default true): when an entry is fresh within its stale-while-revalidate window the stale response is returned immediately and a background revalidation kicks off so the next caller sees a refreshed entry. Pass false to revalidate inline (lower memory churn, higher request latency).
var cache = b.httpClient.cache.create({
store: b.httpClient.cache.memoryStore({ maxBytes: 32 * 1024 * 1024 }),
sharedCache: true,
defaultMaxStale: 5,
audit: b.audit,
});
var res = await b.httpClient.request({
url: "https://api.example.com/users/42",
cache: cache,
});
// res.headers["x-blamejs-cache"] === "MISS" (first call)
Last updated 2026-08-08T16:39:49.652Z by seeder.