OCaml HTTP cookie handling library with support for Eio-based storage jars

Enhance documentation with odoc extension plugins

- Convert RFC URL references to semantic @rfc tags across cookeio, imap, jmap
- Add security admonition warning to cookeio cookie documentation
- Add MSC protocol flow diagram to imap.mli showing IMAP session sequence
- Add Mermaid sequence diagram to jmap.mli showing JMAP request batching

Uses the new odoc-rfc-extension, odoc-admonition-extension, odoc-msc-extension,
and odoc-mermaid-extension plugins to generate styled, linked documentation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+49 -45
+31 -27
lib/core/cookeio.mli
··· 15 This library provides a complete cookie implementation following RFC 6265 16 while integrating Eio for efficient asynchronous operations. 17 18 {2 Cookie Format and Structure} 19 20 Cookies are set via the Set-Cookie HTTP response header ··· 45 - IP addresses require exact match only 46 - Path matching requires exact match or prefix with "/" separator 47 48 - @see <https://datatracker.ietf.org/doc/html/rfc6265> RFC 6265 - HTTP State Management Mechanism 49 50 {2 Standards and References} 51 ··· 89 - [`None]: Cookie sent for all cross-site requests (requires [secure] 90 flag per RFC 6265bis) 91 92 - @see <https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7> RFC 6265bis Section 5.4.7 - The SameSite Attribute *) 93 94 val equal : t -> t -> bool 95 (** Equality function for same-site values. *) ··· 108 - [`DateTime time]: Persistent cookie that expires at specific time 109 (persistent-flag = true) 110 111 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 112 113 val equal : t -> t -> bool 114 (** Equality function for expiration values. *) ··· 126 cookies with the same [name], [domain], and [path] will overwrite each other 127 when stored. 128 129 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 130 131 (** {1 Cookie Accessors} *) 132 ··· 140 val path : t -> string 141 (** Get the path of a cookie. 142 143 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.4> RFC 6265 Section 5.2.4 - The Path Attribute *) 144 145 val name : t -> string 146 (** Get the name of a cookie. *) ··· 168 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5} RFC 6265 Section 5.2.5}, 169 Secure cookies are only sent over HTTPS connections. 170 171 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5> RFC 6265 Section 5.2.5 - The Secure Attribute *) 172 173 val http_only : t -> bool 174 (** Check if cookie has the HttpOnly flag. ··· 176 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.6} RFC 6265 Section 5.2.6}, 177 HttpOnly cookies are not accessible to client-side scripts. 178 179 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.6> RFC 6265 Section 5.2.6 - The HttpOnly Attribute *) 180 181 val partitioned : t -> bool 182 (** Check if cookie has the Partitioned attribute. ··· 203 - Cookie set on "example.com" without Domain attribute: host_only=true, 204 matches only example.com, not sub.example.com 205 206 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 207 208 val expires : t -> Expiration.t option 209 (** Get the expiration attribute if set. ··· 216 Both [max_age] and [expires] can be present simultaneously. This library 217 stores both independently. 218 219 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.1> RFC 6265 Section 5.2.1 - The Expires Attribute *) 220 221 val max_age : t -> Ptime.Span.t option 222 (** Get the max-age attribute if set. ··· 229 230 This library stores both independently and serializes both when present. 231 232 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2> RFC 6265 Section 5.2.2 - The Max-Age Attribute *) 233 234 val same_site : t -> SameSite.t option 235 (** Get the same-site policy of a cookie. 236 237 - @see <https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7> RFC 6265bis Section 5.4.7 - The SameSite Attribute *) 238 239 val creation_time : t -> Ptime.t 240 (** Get the creation time of a cookie. ··· 286 Note: If [partitioned] is [true], the cookie must also be [secure]. Invalid 287 combinations will result in validation errors. 288 289 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 290 291 (** {1 RFC 6265 Validation} 292 ··· 320 These functions return [Ok value] on success or [Error msg] with a detailed 321 explanation of why validation failed. 322 323 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1> RFC 6265 Section 4.1.1 - Syntax *) 324 325 module Validate : sig 326 val cookie_name : string -> (string, string) result ··· 341 @param name The cookie name to validate 342 @return [Ok name] if valid, [Error message] with explanation if invalid 343 344 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1> RFC 6265 Section 4.1.1 345 - @see <https://datatracker.ietf.org/doc/html/rfc2616#section-2.2> RFC 2616 Section 2.2 - Basic Rules *) 346 347 val cookie_value : string -> (string, string) result 348 (** Validate a cookie value per RFC 6265. ··· 364 @param value The cookie value to validate 365 @return [Ok value] if valid, [Error message] with explanation if invalid 366 367 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1> RFC 6265 Section 4.1.1 *) 368 369 val domain_value : string -> (string, string) result 370 (** Validate a domain attribute value. ··· 388 @param domain The domain value to validate (leading dot is stripped first) 389 @return [Ok domain] if valid, [Error message] with explanation if invalid 390 391 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.2.3> RFC 6265 Section 4.1.2.3 392 - @see <https://datatracker.ietf.org/doc/html/rfc1034#section-3.5> RFC 1034 Section 3.5 *) 393 394 val path_value : string -> (string, string) result 395 (** Validate a path attribute value. ··· 400 @param path The path value to validate 401 @return [Ok path] if valid, [Error message] with explanation if invalid 402 403 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1> RFC 6265 Section 4.1.1 *) 404 405 val max_age : int -> (int, string) result 406 (** Validate a Max-Age attribute value. ··· 413 @param seconds The Max-Age value in seconds 414 @return [Ok seconds] always (negative values are handled in parsing) 415 416 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1> RFC 6265 Section 4.1.1 417 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2> RFC 6265 Section 5.2.2 *) 418 end 419 420 (** {1 Cookie Creation and Parsing} *) ··· 468 {[of_set_cookie_header ~now:(fun () -> Ptime_clock.now ()) 469 ~domain:"example.com" ~path:"/" "session=abc123; Secure; HttpOnly"]} 470 471 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2> RFC 6265 Section 5.2 - The Set-Cookie Header 472 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model (public suffix check) 473 - @see <https://publicsuffix.org/list/> Public Suffix List *) 474 475 val of_cookie_header : 476 now:(unit -> Ptime.t) -> ··· 503 {[of_cookie_header ~now:(fun () -> Ptime_clock.now ()) ~domain:"example.com" 504 ~path:"/" "session=abc; theme=dark"]} 505 506 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.2> RFC 6265 Section 4.2 - The Cookie Header *) 507 508 val make_cookie_header : t list -> string 509 (** Create Cookie header value from cookies. ··· 517 Example: [make_cookie_header cookies] might return 518 ["session=abc123; theme=dark"] 519 520 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.2> RFC 6265 Section 4.2 - The Cookie Header *) 521 522 val make_set_cookie_header : t -> string 523 (** Create Set-Cookie header value from a cookie. ··· 530 The Expires attribute uses rfc1123-date format ("Sun, 06 Nov 1994 08:49:37 GMT") 531 as specified in {{:https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1} Section 4.1.1}. 532 533 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1> RFC 6265 Section 4.1 - The Set-Cookie Header *) 534 535 (** {1 Pretty Printing} *) 536
··· 15 This library provides a complete cookie implementation following RFC 6265 16 while integrating Eio for efficient asynchronous operations. 17 18 + @admonition.warning Cookies may contain sensitive information such as 19 + session tokens. Always use the [Secure] flag for authentication cookies 20 + and consider [HttpOnly] to prevent XSS attacks from accessing cookie values. 21 + 22 {2 Cookie Format and Structure} 23 24 Cookies are set via the Set-Cookie HTTP response header ··· 49 - IP addresses require exact match only 50 - Path matching requires exact match or prefix with "/" separator 51 52 + @rfc 6265 53 54 {2 Standards and References} 55 ··· 93 - [`None]: Cookie sent for all cross-site requests (requires [secure] 94 flag per RFC 6265bis) 95 96 + @admonition.note The SameSite attribute is defined in RFC 6265bis (draft), not the original RFC 6265. *) 97 98 val equal : t -> t -> bool 99 (** Equality function for same-site values. *) ··· 112 - [`DateTime time]: Persistent cookie that expires at specific time 113 (persistent-flag = true) 114 115 + @rfc 6265 Section 5.3 *) 116 117 val equal : t -> t -> bool 118 (** Equality function for expiration values. *) ··· 130 cookies with the same [name], [domain], and [path] will overwrite each other 131 when stored. 132 133 + @rfc 6265 Section 5.3 *) 134 135 (** {1 Cookie Accessors} *) 136 ··· 144 val path : t -> string 145 (** Get the path of a cookie. 146 147 + @rfc 6265 Section 5.2.4 *) 148 149 val name : t -> string 150 (** Get the name of a cookie. *) ··· 172 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5} RFC 6265 Section 5.2.5}, 173 Secure cookies are only sent over HTTPS connections. 174 175 + @rfc 6265 Section 5.2.5 *) 176 177 val http_only : t -> bool 178 (** Check if cookie has the HttpOnly flag. ··· 180 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.6} RFC 6265 Section 5.2.6}, 181 HttpOnly cookies are not accessible to client-side scripts. 182 183 + @rfc 6265 Section 5.2.6 *) 184 185 val partitioned : t -> bool 186 (** Check if cookie has the Partitioned attribute. ··· 207 - Cookie set on "example.com" without Domain attribute: host_only=true, 208 matches only example.com, not sub.example.com 209 210 + @rfc 6265 Section 5.3 *) 211 212 val expires : t -> Expiration.t option 213 (** Get the expiration attribute if set. ··· 220 Both [max_age] and [expires] can be present simultaneously. This library 221 stores both independently. 222 223 + @rfc 6265 Section 5.2.1 *) 224 225 val max_age : t -> Ptime.Span.t option 226 (** Get the max-age attribute if set. ··· 233 234 This library stores both independently and serializes both when present. 235 236 + @rfc 6265 Section 5.2.2 *) 237 238 val same_site : t -> SameSite.t option 239 (** Get the same-site policy of a cookie. 240 241 + *) 242 243 val creation_time : t -> Ptime.t 244 (** Get the creation time of a cookie. ··· 290 Note: If [partitioned] is [true], the cookie must also be [secure]. Invalid 291 combinations will result in validation errors. 292 293 + @rfc 6265 Section 5.3 *) 294 295 (** {1 RFC 6265 Validation} 296 ··· 324 These functions return [Ok value] on success or [Error msg] with a detailed 325 explanation of why validation failed. 326 327 + @rfc 6265 Section 4.1.1 *) 328 329 module Validate : sig 330 val cookie_name : string -> (string, string) result ··· 345 @param name The cookie name to validate 346 @return [Ok name] if valid, [Error message] with explanation if invalid 347 348 + @rfc 6265 Section 4.1.1 349 + @rfc 2616 Section 2.2 *) 350 351 val cookie_value : string -> (string, string) result 352 (** Validate a cookie value per RFC 6265. ··· 368 @param value The cookie value to validate 369 @return [Ok value] if valid, [Error message] with explanation if invalid 370 371 + @rfc 6265 Section 4.1.1 *) 372 373 val domain_value : string -> (string, string) result 374 (** Validate a domain attribute value. ··· 392 @param domain The domain value to validate (leading dot is stripped first) 393 @return [Ok domain] if valid, [Error message] with explanation if invalid 394 395 + @rfc 6265 Section 4.1.2.3 396 + @rfc 1034 Section 3.5 *) 397 398 val path_value : string -> (string, string) result 399 (** Validate a path attribute value. ··· 404 @param path The path value to validate 405 @return [Ok path] if valid, [Error message] with explanation if invalid 406 407 + @rfc 6265 Section 4.1.1 *) 408 409 val max_age : int -> (int, string) result 410 (** Validate a Max-Age attribute value. ··· 417 @param seconds The Max-Age value in seconds 418 @return [Ok seconds] always (negative values are handled in parsing) 419 420 + @rfc 6265 Section 4.1.1 421 + @rfc 6265 Section 5.2.2 *) 422 end 423 424 (** {1 Cookie Creation and Parsing} *) ··· 472 {[of_set_cookie_header ~now:(fun () -> Ptime_clock.now ()) 473 ~domain:"example.com" ~path:"/" "session=abc123; Secure; HttpOnly"]} 474 475 + @rfc 6265 Section 5.2 476 + @rfc 6265 Section 5.3 477 + *) 478 479 val of_cookie_header : 480 now:(unit -> Ptime.t) -> ··· 507 {[of_cookie_header ~now:(fun () -> Ptime_clock.now ()) ~domain:"example.com" 508 ~path:"/" "session=abc; theme=dark"]} 509 510 + @rfc 6265 Section 4.2 *) 511 512 val make_cookie_header : t list -> string 513 (** Create Cookie header value from cookies. ··· 521 Example: [make_cookie_header cookies] might return 522 ["session=abc123; theme=dark"] 523 524 + @rfc 6265 Section 4.2 *) 525 526 val make_set_cookie_header : t -> string 527 (** Create Set-Cookie header value from a cookie. ··· 534 The Expires attribute uses rfc1123-date format ("Sun, 06 Nov 1994 08:49:37 GMT") 535 as specified in {{:https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1} Section 4.1.1}. 536 537 + @rfc 6265 Section 4.1 *) 538 539 (** {1 Pretty Printing} *) 540
+11 -11
lib/jar/cookeio_jar.ml
··· 25 (** Two cookies are considered identical if they have the same name, domain, 26 and path. This is used when replacing or removing cookies. 27 28 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 29 let cookie_identity_matches c1 c2 = 30 Cookeio.name c1 = Cookeio.name c2 31 && Cookeio.domain c1 = Cookeio.domain c2 ··· 36 Per RFC 6265, the Domain attribute value is canonicalized by removing any 37 leading dot before storage. 38 39 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3> RFC 6265 Section 5.2.3 - The Domain Attribute *) 40 let normalize_domain domain = 41 match String.starts_with ~prefix:"." domain with 42 | true when String.length domain > 1 -> ··· 63 Per RFC 6265 Section 5.1.3, domain matching should only apply to hostnames, 64 not IP addresses. IP addresses require exact match only. 65 66 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3> RFC 6265 Section 5.1.3 - Domain Matching *) 67 let is_ip_address domain = Result.is_ok (Ipaddr.of_string domain) 68 69 (** Check if a cookie domain matches a request domain. ··· 83 @param request_domain The domain from the HTTP request 84 @return true if the cookie should be sent for this domain 85 86 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3> RFC 6265 Section 5.1.3 - Domain Matching 87 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model (host-only-flag) *) 88 let domain_matches ~host_only cookie_domain request_domain = 89 request_domain = cookie_domain 90 || (not (is_ip_address request_domain || host_only) ··· 103 @param request_path The path from the HTTP request 104 @return true if the cookie should be sent for this path 105 106 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4> RFC 6265 Section 5.1.4 - Paths and Path-Match *) 107 let path_matches cookie_path request_path = 108 if cookie_path = request_path then true 109 else if String.starts_with ~prefix:cookie_path request_path then ··· 124 @param clock The Eio clock for current time 125 @return true if the cookie has expired 126 127 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 128 let is_expired cookie clock = 129 match Cookeio.expires cookie with 130 | None -> false (* No expiration *) ··· 169 @param new_cookie The new cookie to add 170 @return The new cookie with creation_time preserved from old_cookie if present 171 172 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 173 let preserve_creation_time old_cookie_opt new_cookie = 174 match old_cookie_opt with 175 | None -> new_cookie ··· 261 @param clock The Eio clock for timestamps 262 @return A new cookie configured to cause deletion 263 264 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 265 let make_removal_cookie cookie ~clock = 266 let now = 267 Ptime.of_float_s (Eio.Time.now clock) |> Option.value ~default:Ptime.epoch ··· 315 1. Cookies with longer paths listed first 316 2. Among equal-length paths, cookies with earlier creation-times first 317 318 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.4> RFC 6265 Section 5.4 - The Cookie Header *) 319 let compare_cookie_order c1 c2 = 320 let path1_len = String.length (Cookeio.path c1) in 321 let path2_len = String.length (Cookeio.path c2) in ··· 343 @param is_secure Whether the request is over a secure channel (HTTPS) 344 @return List of cookies that should be included in the Cookie header, sorted 345 346 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.4> RFC 6265 Section 5.4 - The Cookie Header *) 347 let get_cookies jar ~clock ~domain:request_domain ~path:request_path ~is_secure 348 = 349 Log.debug (fun m ->
··· 25 (** Two cookies are considered identical if they have the same name, domain, 26 and path. This is used when replacing or removing cookies. 27 28 + @rfc 6265 Section 5.3 *) 29 let cookie_identity_matches c1 c2 = 30 Cookeio.name c1 = Cookeio.name c2 31 && Cookeio.domain c1 = Cookeio.domain c2 ··· 36 Per RFC 6265, the Domain attribute value is canonicalized by removing any 37 leading dot before storage. 38 39 + @rfc 6265 Section 5.2.3 *) 40 let normalize_domain domain = 41 match String.starts_with ~prefix:"." domain with 42 | true when String.length domain > 1 -> ··· 63 Per RFC 6265 Section 5.1.3, domain matching should only apply to hostnames, 64 not IP addresses. IP addresses require exact match only. 65 66 + @rfc 6265 Section 5.1.3 *) 67 let is_ip_address domain = Result.is_ok (Ipaddr.of_string domain) 68 69 (** Check if a cookie domain matches a request domain. ··· 83 @param request_domain The domain from the HTTP request 84 @return true if the cookie should be sent for this domain 85 86 + @rfc 6265 Section 5.1.3 87 + @rfc 6265 Section 5.3 *) 88 let domain_matches ~host_only cookie_domain request_domain = 89 request_domain = cookie_domain 90 || (not (is_ip_address request_domain || host_only) ··· 103 @param request_path The path from the HTTP request 104 @return true if the cookie should be sent for this path 105 106 + @rfc 6265 Section 5.1.4 *) 107 let path_matches cookie_path request_path = 108 if cookie_path = request_path then true 109 else if String.starts_with ~prefix:cookie_path request_path then ··· 124 @param clock The Eio clock for current time 125 @return true if the cookie has expired 126 127 + @rfc 6265 Section 5.3 *) 128 let is_expired cookie clock = 129 match Cookeio.expires cookie with 130 | None -> false (* No expiration *) ··· 169 @param new_cookie The new cookie to add 170 @return The new cookie with creation_time preserved from old_cookie if present 171 172 + @rfc 6265 Section 5.3 *) 173 let preserve_creation_time old_cookie_opt new_cookie = 174 match old_cookie_opt with 175 | None -> new_cookie ··· 261 @param clock The Eio clock for timestamps 262 @return A new cookie configured to cause deletion 263 264 + @rfc 6265 Section 5.3 *) 265 let make_removal_cookie cookie ~clock = 266 let now = 267 Ptime.of_float_s (Eio.Time.now clock) |> Option.value ~default:Ptime.epoch ··· 315 1. Cookies with longer paths listed first 316 2. Among equal-length paths, cookies with earlier creation-times first 317 318 + @rfc 6265 Section 5.4 *) 319 let compare_cookie_order c1 c2 = 320 let path1_len = String.length (Cookeio.path c1) in 321 let path2_len = String.length (Cookeio.path c2) in ··· 343 @param is_secure Whether the request is over a secure channel (HTTPS) 344 @return List of cookies that should be included in the Cookie header, sorted 345 346 + @rfc 6265 Section 5.4 *) 347 let get_cookies jar ~clock ~domain:request_domain ~path:request_path ~is_secure 348 = 349 Log.debug (fun m ->
+7 -7
lib/jar/cookeio_jar.mli
··· 18 - Delta tracking for Set-Cookie headers 19 - Mozilla format persistence for cross-tool compatibility 20 21 - @see <https://datatracker.ietf.org/doc/html/rfc6265> RFC 6265 - HTTP State Management Mechanism 22 23 {2 Standards and References} 24 ··· 81 creation-time is preserved. This ensures stable cookie ordering per 82 Section 5.4, Step 2. 83 84 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 85 86 val add_original : t -> Cookeio.t -> unit 87 (** Add an original cookie to the jar. ··· 93 Per Section 5.3, Step 11.3, when replacing an existing cookie, the original 94 creation-time is preserved. 95 96 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 97 98 val delta : t -> Cookeio.t list 99 (** Get cookies that need to be sent in Set-Cookie headers. ··· 102 for original cookies that have been removed. Does not include original 103 cookies that were added via {!add_original}. 104 105 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-4.1> RFC 6265 Section 4.1 - Set-Cookie *) 106 107 val remove : t -> clock:_ Eio.Time.clock -> Cookeio.t -> unit 108 (** Remove a cookie from the jar. ··· 114 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.3} RFC 6265 Section 5.3}, 115 cookies are removed by sending a Set-Cookie with an expiry date in the past. 116 117 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model *) 118 119 val get_cookies : 120 t -> ··· 169 @param is_secure Whether the request is over a secure channel (HTTPS) 170 @return List of matching cookies, sorted per RFC 6265 171 172 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.3> RFC 6265 Section 5.3 - Storage Model (expiry) 173 - @see <https://datatracker.ietf.org/doc/html/rfc6265#section-5.4> RFC 6265 Section 5.4 - The Cookie Header *) 174 175 val clear : t -> unit 176 (** Clear all cookies. *)
··· 18 - Delta tracking for Set-Cookie headers 19 - Mozilla format persistence for cross-tool compatibility 20 21 + @rfc 6265 22 23 {2 Standards and References} 24 ··· 81 creation-time is preserved. This ensures stable cookie ordering per 82 Section 5.4, Step 2. 83 84 + @rfc 6265 Section 5.3 *) 85 86 val add_original : t -> Cookeio.t -> unit 87 (** Add an original cookie to the jar. ··· 93 Per Section 5.3, Step 11.3, when replacing an existing cookie, the original 94 creation-time is preserved. 95 96 + @rfc 6265 Section 5.3 *) 97 98 val delta : t -> Cookeio.t list 99 (** Get cookies that need to be sent in Set-Cookie headers. ··· 102 for original cookies that have been removed. Does not include original 103 cookies that were added via {!add_original}. 104 105 + @rfc 6265 Section 4.1 *) 106 107 val remove : t -> clock:_ Eio.Time.clock -> Cookeio.t -> unit 108 (** Remove a cookie from the jar. ··· 114 Per {{:https://datatracker.ietf.org/doc/html/rfc6265#section-5.3} RFC 6265 Section 5.3}, 115 cookies are removed by sending a Set-Cookie with an expiry date in the past. 116 117 + @rfc 6265 Section 5.3 *) 118 119 val get_cookies : 120 t -> ··· 169 @param is_secure Whether the request is over a secure channel (HTTPS) 170 @return List of matching cookies, sorted per RFC 6265 171 172 + @rfc 6265 Section 5.3 173 + @rfc 6265 Section 5.4 *) 174 175 val clear : t -> unit 176 (** Clear all cookies. *)