Cookie - HTTP Cookie Management for OCaml#
Cookie parsing, validation, and jar management following RFC 6265.
Packages#
cookie(moduleCookie): Cookie parsing, creation, and serialization. Handles Set-Cookie and Cookie headers with support for all attributes including SameSite, Partitioned (CHIPS), and HttpOnly.cookie.jar(moduleCookie_jar): Cookie jar storage with domain/path matching, delta tracking, and persistence in Mozilla format.
Installation#
Install with opam:
opam install nox-cookie
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
opam update
opam install nox-cookie
Cookie Attributes#
- Domain: Tail matching for hostnames, exact match for IPs
- Path: Prefix matching with "/" separator
- Secure: HTTPS-only transmission
- HttpOnly: No JavaScript access
- Expires / Max-Age: Cookie lifetime (session cookies when omitted)
- SameSite: Cross-site request behavior (
Strict,Lax,None) - Partitioned: CHIPS partitioned storage (requires Secure)
Usage#
Parsing Headers#
let now () = Ptime_clock.now ()
(* Parse a Set-Cookie response header *)
let parse_set_cookie =
Cookie.of_set_cookie_header ~now ~domain:"example.com" ~path:"/"
"session=abc123; Secure; HttpOnly; SameSite=Strict"
(* Parse a Cookie request header *)
let parse_cookies =
Cookie.of_request_header ~now ~domain:"example.com" ~path:"/"
"session=abc123; theme=dark"
Serializing Headers#
let render_request (cookies : Cookie.t list) = Cookie.request_header cookies
let render_response (cookie : Cookie.t) = Cookie.set_cookie_header cookie
Creating Cookies#
let session_cookie ~now =
Cookie.v ~domain:"example.com" ~path:"/" ~name:"session" ~value:"abc123"
~secure:true ~http_only:true ~same_site:`Strict ~creation_time:(now ())
~last_access:(now ()) ()
Cookie Jar#
let api_cookies ~clock (cookie : Cookie.t) =
let jar = Cookie_jar.v () in
Cookie_jar.add_cookie jar cookie;
let matching =
Cookie_jar.cookies jar ~clock ~domain:"example.com" ~path:"/api"
~is_secure:true
in
Cookie.request_header matching
Delta Tracking#
let log_pending (jar : Cookie_jar.t) =
Cookie_jar.delta jar
|> List.iter (fun c -> Fmt.pr "%s@." (Cookie.set_cookie_header c))
Persistence#
Cookies are persisted in Mozilla format:
let save_jar ~path (jar : Cookie_jar.t) = Cookie_jar.save path jar
let load_jar ~clock ~path = Cookie_jar.load ~clock path
Validation#
The Cookie.Validate module enforces RFC 6265 server requirements:
# Cookie.Validate.cookie_name "session";;
- : (string, string) result = Ok "session"
# Cookie.Validate.cookie_value "abc;123";;
- : (string, string) result =
Error
"Cookie value \"abc;123\" contains invalid characters: semicolon (0x3B). RFC 6265 cookie values may only contain printable ASCII excluding double-quote, comma, semicolon, and backslash"
# Cookie.Validate.domain_value "example.com";;
- : (string, string) result = Ok "example.com"
Licence#
ISC