Module Cache

HTTP Response Caching per RFC 9111

This module provides an in-memory cache for HTTP responses following RFC 9111 (HTTP Caching). It handles cache storage, validation, and freshness calculations.

Cache Keys

Cache entries are keyed by method and effective request URI per RFC 9111. Only safe methods (GET, HEAD) are cached by default.

Examples

  (* Create an in-memory cache *)
  let cache = Cache.Memory.create ~max_entries:1000 () in

  (* Store a response *)
  Cache.Memory.store cache ~key ~response ~request_time ~response_time;

  (* Lookup a cached response *)
  match Cache.Memory.lookup cache ~key ~now with
  | Some (entry, status) ->
    Printf.printf "Cache %s: %s\n"
      (match status with `Fresh -> "hit" | `Stale -> "stale")
      entry.url
  | None -> Printf.printf "Cache miss\n"
val src : Logs.Src.t

Log source for cache operations

Cache Entry

type entry = {
  1. url : string;
    (*

    The effective request URI

    *)
  2. method_ : Method.t;
    (*

    HTTP method used for the request

    *)
  3. status : int;
    (*

    Response status code

    *)
  4. headers : Headers.t;
    (*

    Response headers

    *)
  5. body : string;
    (*

    Response body

    *)
  6. request_time : Ptime.t;
    (*

    When the request was initiated

    *)
  7. response_time : Ptime.t;
    (*

    When the response was received

    *)
  8. date_value : Ptime.t option;
    (*

    Parsed Date header value

    *)
  9. age_value : int;
    (*

    Age header value (0 if not present)

    *)
  10. cache_control : Cache_control.response;
    (*

    Parsed Cache-Control header

    *)
  11. etag : string option;
    (*

    ETag header for validation

    *)
  12. last_modified : string option;
    (*

    Last-Modified header for validation

    *)
  13. vary_headers : (string * string) list;
    (*

    Request header values for Vary matching

    *)
  14. freshness_lifetime : int option;
    (*

    Calculated freshness lifetime in seconds

    *)
}

A cached response entry

type lookup_status =
  1. | Fresh
    (*

    Entry is fresh and can be served directly

    *)
  2. | Stale
    (*

    Entry is stale but might be served with revalidation or max-stale

    *)

Cache lookup result status

Cache Key

type key = {
  1. method_key : Method.t;
  2. uri : string;
  3. vary_values : (string * string) list;
    (*

    Values of Vary headers from request

    *)
}

A cache key for lookups

val make_key : method_:Method.t -> uri:string -> ?request_headers:Headers.t -> ?vary:string list -> unit -> key

Create a cache key.

  • parameter method_

    The HTTP method

  • parameter uri

    The effective request URI

  • parameter request_headers

    Request headers for Vary matching

  • parameter vary

    List of header names from Vary response header

In-Memory Cache

module Memory : sig ... end

In-memory HTTP response cache using a Hashtbl. Thread-safe using Eio.Mutex.

Cache Validation

val needs_validation : entry -> bool

Check if a cached entry needs revalidation with the origin server. True if must-revalidate or no-cache is set.

val validation_headers : entry -> Headers.t

Get headers to send for a conditional request. Includes If-None-Match (from ETag) and/or If-Modified-Since (from Last-Modified).

val is_not_modified : status:int -> bool

Check if a response indicates the cached version is still valid (304).

Vary Header Support

val parse_vary : string -> string list

Parse a Vary header value into a list of header names.

val vary_matches : cached_vary:(string * string) list -> request_headers:Headers.t -> bool

Check if request headers match the cached Vary values.