or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

HTTP Cache Semantics

HTTP Cache Semantics is a JavaScript library that implements HTTP caching rules according to RFC 7234/9111 specifications. It provides the

CachePolicy
class that determines when HTTP responses can be reused from cache, handles cache validation, and manages complex caching scenarios including
Vary
headers, proxy revalidation, and authenticated responses.

Package Information

  • Package Name: http-cache-semantics
  • Package Type: npm
  • Language: JavaScript (CommonJS)
  • Installation:
    npm install http-cache-semantics

Core Imports

const CachePolicy = require("http-cache-semantics");

For ES modules:

import CachePolicy from "http-cache-semantics";

Basic Usage

const CachePolicy = require("http-cache-semantics");

// Create policy from request and response
const policy = new CachePolicy(
  { 
    url: "/api/users",
    method: "GET",
    headers: { "accept": "application/json" }
  },
  { 
    status: 200,
    headers: { "cache-control": "public, max-age=3600" }
  }
);

// Check if response can be stored
if (policy.storable()) {
  // Store in cache with TTL
  cache.set(request.url, {
    policy: policy,
    body: response.body
  }, policy.timeToLive());
}

// Later, check if cached response satisfies new request
const newRequest = { url: "/api/users", headers: {} };
if (policy.satisfiesWithoutRevalidation(newRequest)) {
  // Use cached response with updated headers
  return {
    headers: policy.responseHeaders(),
    body: cachedBody
  };
}

Capabilities

CachePolicy Constructor

Creates a new cache policy instance that tracks cacheability and freshness of HTTP responses.

/**
 * Creates a new CachePolicy instance
 * @param {HttpRequest} req - Incoming client request
 * @param {HttpResponse} res - Received server response  
 * @param {Object} [options={}] - Configuration options
 * @param {boolean} [options.shared=true] - Is cache shared (public proxy) vs private
 * @param {number} [options.cacheHeuristic=0.1] - Fallback heuristic fraction for cache duration
 * @param {number} [options.immutableMinTimeToLive=86400000] - Minimum TTL for immutable responses in ms
 * @param {boolean} [options.ignoreCargoCult=false] - Override nonsense cache headers
 */
constructor(req, res, options = {})

Cache Storage Methods

Methods for determining if a response can be stored and used from cache.

/**
 * Returns true if the response can be stored in cache
 * @returns {boolean} false if response must not be cached
 */
storable()

/**
 * Checks if cached response satisfies new request without revalidation
 * @param {HttpRequest} req - New incoming HTTP request
 * @returns {boolean} true if cached response can be used directly
 */
satisfiesWithoutRevalidation(req)

Advanced Request Evaluation

Comprehensive method for determining cache usage with support for stale-while-revalidate.

/**
 * Evaluates how cached entry can satisfy new request
 * @param {HttpRequest} req - New incoming HTTP request
 * @returns {EvaluationResult} Object with revalidation and response info
 */
evaluateRequest(req)

Response Headers Management

Method for getting properly updated headers when serving cached responses.

/**
 * Returns updated response headers for serving cached response
 * Removes hop-by-hop headers and updates Age/Date
 * @returns {Record<string, string>} Updated headers object for client response
 */
responseHeaders()

Time and Freshness Methods

Methods for determining cache entry age, freshness, and time-to-live.

/**
 * Returns current age of cached response in seconds
 * @returns {number} Age in seconds including resident time
 */
age()

/**
 * Returns maximum age (freshness lifetime) in seconds
 * @returns {number} Max-age value in seconds
 */
maxAge()

/**
 * Returns remaining time cache entry may be useful in milliseconds
 * @returns {number} Time-to-live in milliseconds
 */
timeToLive()

/**
 * Returns true if response is past its expiration date
 * @returns {boolean} true if stale (may still be usable in some cases)
 */
stale()

/**
 * Returns Date header timestamp or response time if invalid
 * @returns {number} Timestamp in milliseconds
 */
date()

Stale Response Handling

Methods for working with stale responses using RFC 5861 extensions.

/**
 * Returns true if stale-while-revalidate is currently allowed
 * @returns {boolean} true if stale response can be used while revalidating
 */
useStaleWhileRevalidate()

Cache Revalidation

Methods for efficiently updating stale cache entries by revalidating with origin server.

/**
 * Returns headers for revalidation request to origin server
 * Allows server to return 304 Not Modified to save bandwidth
 * @param {HttpRequest} incomingReq - New incoming HTTP request
 * @returns {Record<string, string>} Headers object for revalidation request
 */
revalidationHeaders(incomingReq)

/**
 * Creates updated policy from revalidation response
 * @param {HttpRequest} request - Latest HTTP request for cached entry
 * @param {HttpResponse} response - Revalidation response from origin server
 * @returns {RevalidationResult} Object with updated policy and modification status
 */
revalidatedPolicy(request, response)

Serialization Methods

Methods for storing and restoring cache policy objects.

/**
 * Serializes CachePolicy instance to JSON-serializable object
 * @returns {Object} Serialized object for storage
 */
toObject()

/**
 * Creates CachePolicy instance from serialized object
 * @param {Object} obj - Previously serialized CachePolicy object
 * @returns {CachePolicy} Restored CachePolicy instance
 */
static fromObject(obj)

Utility Methods

/**
 * Returns current time in milliseconds (can be monkey-patched for testing)
 * @returns {number} Current timestamp
 */
now()

Types

/**
 * HTTP request object
 * @typedef {Object} HttpRequest
 * @property {Record<string, string>} headers - Request headers (lowercase names)
 * @property {string} [method="GET"] - HTTP method
 * @property {string} [url] - Request URL
 */

/**
 * HTTP response object  
 * @typedef {Object} HttpResponse
 * @property {Record<string, string>} headers - Response headers (lowercase names)
 * @property {number} [status=200] - HTTP status code
 */

/**
 * Result from evaluateRequest method
 * @typedef {Object} EvaluationResult
 * @property {Object} [response] - Cached response can be used
 * @property {Record<string, string>} [response.headers] - Updated headers for cached response
 * @property {Object} [revalidation] - Revalidation needed
 * @property {Record<string, string>} [revalidation.headers] - Headers for revalidation request
 * @property {boolean} [revalidation.synchronous] - Whether to wait for revalidation
 */

/**
 * Result from revalidatedPolicy method
 * @typedef {Object} RevalidationResult  
 * @property {CachePolicy} policy - Updated CachePolicy instance
 * @property {boolean} modified - Whether response body changed
 * @property {boolean} matches - Whether revalidation response matches
 */

Complete Usage Example

const CachePolicy = require("http-cache-semantics");

// Cache storage implementation
const cache = new Map();

async function handleRequest(incomingRequest) {
  // Try to get from cache
  const cached = cache.get(incomingRequest.url);
  
  if (!cached) {
    // Cache miss - fetch from origin
    const originResponse = await fetch(incomingRequest);
    const policy = new CachePolicy(incomingRequest, originResponse);
    
    if (policy.storable()) {
      cache.set(incomingRequest.url, {
        policy: policy,
        body: originResponse.body
      });
    }
    
    return {
      headers: policy.responseHeaders(),
      body: originResponse.body
    };
  }
  
  // Evaluate cached entry
  const { revalidation, response } = cached.policy.evaluateRequest(incomingRequest);
  
  if (revalidation) {
    // Need to revalidate with origin
    const revalidationRequest = {
      ...incomingRequest,
      headers: revalidation.headers
    };
    
    const revalidationResponse = await fetch(revalidationRequest);
    const { policy: newPolicy, modified } = cached.policy.revalidatedPolicy(
      incomingRequest, 
      revalidationResponse
    );
    
    const body = modified ? revalidationResponse.body : cached.body;
    
    if (newPolicy.storable()) {
      cache.set(incomingRequest.url, {
        policy: newPolicy,
        body: body
      });
    }
    
    if (revalidation.synchronous) {
      // Must wait for revalidation
      return {
        headers: newPolicy.responseHeaders(),
        body: body
      };
    }
  }
  
  // Use cached response
  return {
    headers: response.headers,
    body: cached.body
  };
}