···11-let src = Logs.Src.create "requests.cookie_jar" ~doc:"HTTP Cookie Jar"
22-module Log = (val Logs.src_log src : Logs.LOG)
33-44-(** Cookie same-site policy *)
55-type same_site = [`Strict | `Lax | `None]
66-77-(** HTTP Cookie *)
88-type cookie = {
99- domain : string;
1010- path : string;
1111- name : string;
1212- value : string;
1313- secure : bool;
1414- http_only : bool;
1515- expires : Ptime.t option;
1616- same_site : same_site option;
1717- creation_time : Ptime.t;
1818- last_access : Ptime.t;
1919-}
2020-2121-(** Cookie jar for storing and managing cookies *)
2222-type t = {
2323- mutable cookies : cookie list;
2424- mutex : Eio.Mutex.t;
2525-}
2626-2727-(** {1 Creation} *)
2828-2929-let create () =
3030- Log.debug (fun m -> m "Creating new empty cookie jar");
3131- { cookies = []; mutex = Eio.Mutex.create () }
3232-3333-(** {1 Cookie Matching Helpers} *)
3434-3535-let domain_matches cookie_domain request_domain =
3636- (* Cookie domain .example.com matches example.com and sub.example.com *)
3737- if String.starts_with ~prefix:"." cookie_domain then
3838- let domain = String.sub cookie_domain 1 (String.length cookie_domain - 1) in
3939- request_domain = domain ||
4040- String.ends_with ~suffix:("." ^ domain) request_domain
4141- else
4242- cookie_domain = request_domain
4343-4444-let path_matches cookie_path request_path =
4545- (* Cookie path /foo matches /foo, /foo/, /foo/bar *)
4646- String.starts_with ~prefix:cookie_path request_path
4747-4848-let is_expired cookie clock =
4949- match cookie.expires with
5050- | None -> false (* Session cookie *)
5151- | Some exp_time ->
5252- let now = Ptime.of_float_s (Eio.Time.now clock) |> Option.value ~default:(Ptime.epoch) in
5353- Ptime.compare now exp_time > 0
5454-5555-(** {1 Cookie Parsing} *)
5656-5757-let parse_cookie_attribute ~url:_ attr value cookie =
5858- let attr_lower = String.lowercase_ascii attr in
5959- match attr_lower with
6060- | "domain" -> { cookie with domain = value }
6161- | "path" -> { cookie with path = value }
6262- | "expires" ->
6363- (* Parse various date formats *)
6464- (try
6565- let time, _tz_offset, _tz_string = Ptime.of_rfc3339 value |> Result.get_ok in
6666- { cookie with expires = Some time }
6767- with _ ->
6868- Log.debug (fun m -> m "Failed to parse expires: %s" value);
6969- cookie)
7070- | "max-age" ->
7171- (try
7272- let seconds = int_of_string value in
7373- let now = Unix.time () in
7474- let expires = Ptime.of_float_s (now +. float_of_int seconds) in
7575- { cookie with expires }
7676- with _ -> cookie)
7777- | "secure" -> { cookie with secure = true }
7878- | "httponly" -> { cookie with http_only = true }
7979- | "samesite" ->
8080- let same_site = match String.lowercase_ascii value with
8181- | "strict" -> Some `Strict
8282- | "lax" -> Some `Lax
8383- | "none" -> Some `None
8484- | _ -> None
8585- in
8686- { cookie with same_site }
8787- | _ -> cookie
8888-8989-let rec parse_set_cookie ~url value =
9090- Log.debug (fun m -> m "Parsing Set-Cookie: %s" value);
9191-9292- let uri = Uri.of_string url in
9393- let default_domain = Uri.host_with_default ~default:"localhost" uri in
9494- let default_path =
9595- let p = Uri.path uri in
9696- if p = "" then "/"
9797- else
9898- let last_slash = String.rindex_opt p '/' in
9999- match last_slash with
100100- | None -> "/"
101101- | Some i -> String.sub p 0 (i + 1)
102102- in
103103-104104- (* Split into attributes *)
105105- let parts = String.split_on_char ';' value |> List.map String.trim in
106106-107107- match parts with
108108- | [] -> None
109109- | name_value :: attrs ->
110110- (* Parse name=value *)
111111- (match String.index_opt name_value '=' with
112112- | None -> None
113113- | Some eq_pos ->
114114- let name = String.sub name_value 0 eq_pos |> String.trim in
115115- let value = String.sub name_value (eq_pos + 1)
116116- (String.length name_value - eq_pos - 1) |> String.trim in
117117-118118- let now = Ptime.of_float_s (Unix.time ()) |> Option.value ~default:Ptime.epoch in
119119- let base_cookie = {
120120- name;
121121- value;
122122- domain = default_domain;
123123- path = default_path;
124124- secure = false;
125125- http_only = false;
126126- expires = None;
127127- same_site = None;
128128- creation_time = now;
129129- last_access = now;
130130- } in
131131-132132- (* Parse attributes *)
133133- let cookie = List.fold_left (fun cookie attr ->
134134- match String.index_opt attr '=' with
135135- | None -> parse_cookie_attribute ~url attr "" cookie
136136- | Some eq ->
137137- let attr_name = String.sub attr 0 eq |> String.trim in
138138- let attr_value = String.sub attr (eq + 1)
139139- (String.length attr - eq - 1) |> String.trim in
140140- parse_cookie_attribute ~url attr_name attr_value cookie
141141- ) base_cookie attrs in
142142-143143- Log.debug (fun m -> m "Parsed cookie: %a" pp_cookie cookie);
144144- Some cookie)
145145-146146-and make_cookie_header cookies =
147147- cookies
148148- |> List.map (fun c -> Printf.sprintf "%s=%s" c.name c.value)
149149- |> String.concat "; "
150150-151151-(** {1 Pretty Printing} *)
152152-153153-and pp_same_site ppf = function
154154- | `Strict -> Format.pp_print_string ppf "Strict"
155155- | `Lax -> Format.pp_print_string ppf "Lax"
156156- | `None -> Format.pp_print_string ppf "None"
157157-158158-and pp_cookie ppf cookie =
159159- Format.fprintf ppf "@[<hov 2>{ name=%S;@ value=%S;@ domain=%S;@ path=%S;@ \
160160- secure=%b;@ http_only=%b;@ expires=%a;@ same_site=%a }@]"
161161- cookie.name
162162- cookie.value
163163- cookie.domain
164164- cookie.path
165165- cookie.secure
166166- cookie.http_only
167167- (Format.pp_print_option Ptime.pp) cookie.expires
168168- (Format.pp_print_option pp_same_site) cookie.same_site
169169-170170-let pp ppf t =
171171- Eio.Mutex.lock t.mutex;
172172- let cookies = t.cookies in
173173- Eio.Mutex.unlock t.mutex;
174174-175175- Format.fprintf ppf "@[<v>CookieJar with %d cookies:@," (List.length cookies);
176176- List.iter (fun cookie ->
177177- Format.fprintf ppf " %a@," pp_cookie cookie
178178- ) cookies;
179179- Format.fprintf ppf "@]"
180180-181181-(** {1 Cookie Management} *)
182182-183183-let add_cookie t cookie =
184184- Log.debug (fun m -> m "Adding cookie: %s=%s for domain %s"
185185- cookie.name cookie.value cookie.domain);
186186-187187- Eio.Mutex.lock t.mutex;
188188- (* Remove existing cookie with same name, domain, and path *)
189189- t.cookies <- List.filter (fun c ->
190190- not (c.name = cookie.name && c.domain = cookie.domain && c.path = cookie.path)
191191- ) t.cookies;
192192- t.cookies <- cookie :: t.cookies;
193193- Eio.Mutex.unlock t.mutex
194194-195195-let extract_from_headers t ~url headers =
196196- Log.debug (fun m -> m "Extracting cookies from headers for URL: %s" url);
197197-198198- let set_cookie_values = Headers.get_multi "set-cookie" headers in
199199- List.iter (fun value ->
200200- match parse_set_cookie ~url value with
201201- | Some cookie -> add_cookie t cookie
202202- | None -> Log.warn (fun m -> m "Failed to parse Set-Cookie header: %s" value)
203203- ) set_cookie_values
204204-205205-let get_cookies t ~url =
206206- let uri = Uri.of_string url in
207207- let domain = Uri.host_with_default ~default:"localhost" uri in
208208- let path = Uri.path uri in
209209- let is_secure = Uri.scheme uri = Some "https" in
210210-211211- Log.debug (fun m -> m "Getting cookies for domain=%s path=%s secure=%b"
212212- domain path is_secure);
213213-214214- Eio.Mutex.lock t.mutex;
215215- let applicable = List.filter (fun cookie ->
216216- domain_matches cookie.domain domain &&
217217- path_matches cookie.path path &&
218218- (not cookie.secure || is_secure)
219219- ) t.cookies in
220220-221221- (* Update last access time *)
222222- let now = Ptime.of_float_s (Unix.time ()) |> Option.value ~default:Ptime.epoch in
223223- let updated = List.map (fun c ->
224224- if List.memq c applicable then
225225- { c with last_access = now }
226226- else c
227227- ) t.cookies in
228228- t.cookies <- updated;
229229- Eio.Mutex.unlock t.mutex;
230230-231231- Log.debug (fun m -> m "Found %d applicable cookies" (List.length applicable));
232232- applicable
233233-234234-let add_to_headers t ~url headers =
235235- let cookies = get_cookies t ~url in
236236- if cookies = [] then headers
237237- else
238238- let cookie_header = make_cookie_header cookies in
239239- Log.debug (fun m -> m "Adding Cookie header: %s" cookie_header);
240240- Headers.add "cookie" cookie_header headers
241241-242242-let clear t =
243243- Log.info (fun m -> m "Clearing all cookies");
244244- Eio.Mutex.lock t.mutex;
245245- t.cookies <- [];
246246- Eio.Mutex.unlock t.mutex
247247-248248-let clear_expired t ~clock =
249249- Eio.Mutex.lock t.mutex;
250250- let before_count = List.length t.cookies in
251251- t.cookies <- List.filter (fun c -> not (is_expired c clock)) t.cookies;
252252- let removed = before_count - List.length t.cookies in
253253- Eio.Mutex.unlock t.mutex;
254254- Log.info (fun m -> m "Cleared %d expired cookies" removed)
255255-256256-let clear_session_cookies t =
257257- Eio.Mutex.lock t.mutex;
258258- let before_count = List.length t.cookies in
259259- t.cookies <- List.filter (fun c -> c.expires <> None) t.cookies;
260260- let removed = before_count - List.length t.cookies in
261261- Eio.Mutex.unlock t.mutex;
262262- Log.info (fun m -> m "Cleared %d session cookies" removed)
263263-264264-let count t =
265265- Eio.Mutex.lock t.mutex;
266266- let n = List.length t.cookies in
267267- Eio.Mutex.unlock t.mutex;
268268- n
269269-270270-(** {1 Mozilla Format} *)
271271-272272-let to_mozilla_format_internal t =
273273- let buffer = Buffer.create 1024 in
274274- Buffer.add_string buffer "# Netscape HTTP Cookie File\n";
275275- Buffer.add_string buffer "# This is a generated file! Do not edit.\n\n";
276276-277277- List.iter (fun cookie ->
278278- let include_subdomains =
279279- if String.starts_with ~prefix:"." cookie.domain then "TRUE" else "FALSE" in
280280- let secure = if cookie.secure then "TRUE" else "FALSE" in
281281- let expires = match cookie.expires with
282282- | None -> "0" (* Session cookie *)
283283- | Some t ->
284284- let epoch = Ptime.to_float_s t |> int_of_float |> string_of_int in
285285- epoch
286286- in
287287-288288- Buffer.add_string buffer (Printf.sprintf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
289289- cookie.domain
290290- include_subdomains
291291- cookie.path
292292- secure
293293- expires
294294- cookie.name
295295- cookie.value)
296296- ) t.cookies;
297297-298298- Buffer.contents buffer
299299-300300-let to_mozilla_format t =
301301- Eio.Mutex.lock t.mutex;
302302- let result = to_mozilla_format_internal t in
303303- Eio.Mutex.unlock t.mutex;
304304- result
305305-306306-let from_mozilla_format content =
307307- Log.debug (fun m -> m "Parsing Mozilla format cookies");
308308- let jar = create () in
309309-310310- let lines = String.split_on_char '\n' content in
311311- List.iter (fun line ->
312312- let line = String.trim line in
313313- if line <> "" && not (String.starts_with ~prefix:"#" line) then
314314- match String.split_on_char '\t' line with
315315- | [domain; _include_subdomains; path; secure; expires; name; value] ->
316316- let now = Ptime.of_float_s (Unix.time ()) |> Option.value ~default:Ptime.epoch in
317317- let expires =
318318- let exp_int = try int_of_string expires with _ -> 0 in
319319- if exp_int = 0 then None
320320- else Ptime.of_float_s (float_of_int exp_int)
321321- in
322322-323323- let cookie = {
324324- domain;
325325- path;
326326- name;
327327- value;
328328- secure = (secure = "TRUE");
329329- http_only = false; (* Not stored in Mozilla format *)
330330- expires;
331331- same_site = None; (* Not stored in Mozilla format *)
332332- creation_time = now;
333333- last_access = now;
334334- } in
335335- add_cookie jar cookie;
336336- Log.debug (fun m -> m "Loaded cookie: %s=%s" name value)
337337- | _ ->
338338- Log.warn (fun m -> m "Invalid cookie line: %s" line)
339339- ) lines;
340340-341341- Log.info (fun m -> m "Loaded %d cookies" (List.length jar.cookies));
342342- jar
343343-344344-(** {1 File Operations} *)
345345-346346-(** Get cookie file path - uses XDG data directory or provided path *)
347347-let get_cookie_file ?xdg ?path () =
348348- match xdg, path with
349349- | Some xdg_ctx, _ ->
350350- (* Use XDG data directory for cookies *)
351351- let data_dir = Xdge.data_dir xdg_ctx in
352352- Eio.Path.(data_dir / "cookies.txt")
353353- | None, Some p -> p
354354- | None, None ->
355355- failwith "Cookie_jar: either xdg or path must be provided"
356356-357357-let load ?xdg ?path () =
358358- let cookie_file = get_cookie_file ?xdg ?path () in
359359- Log.info (fun m -> m "Loading cookies from %a" Eio.Path.pp cookie_file);
360360-361361- try
362362- let content = Eio.Path.load cookie_file in
363363- from_mozilla_format content
364364- with
365365- | Eio.Io _ ->
366366- Log.info (fun m -> m "Cookie file not found, creating empty jar");
367367- create ()
368368- | exn ->
369369- Log.err (fun m -> m "Failed to load cookies: %s" (Printexc.to_string exn));
370370- create ()
371371-372372-let save ?xdg ?path t =
373373- let cookie_file = get_cookie_file ?xdg ?path () in
374374- Log.info (fun m -> m "Saving %d cookies to %a" (List.length t.cookies) Eio.Path.pp cookie_file);
375375-376376- let content = to_mozilla_format t in
377377-378378- try
379379- Eio.Path.save ~create:(`Or_truncate 0o600) cookie_file content;
380380- Log.debug (fun m -> m "Cookies saved successfully")
381381- with exn ->
382382- Log.err (fun m -> m "Failed to save cookies: %s" (Printexc.to_string exn))
-104
stack/requests/lib/cookie_jar.mli
···11-(** HTTP Cookie Jar with Mozilla format persistence support *)
22-33-open Eio
44-55-(** Cookie same-site policy *)
66-type same_site = [`Strict | `Lax | `None]
77-88-(** HTTP Cookie *)
99-type cookie = {
1010- domain : string; (** Domain that set the cookie *)
1111- path : string; (** Path scope for the cookie *)
1212- name : string; (** Cookie name *)
1313- value : string; (** Cookie value *)
1414- secure : bool; (** Only send over HTTPS *)
1515- http_only : bool; (** Not accessible to JavaScript *)
1616- expires : Ptime.t option; (** Expiry time, None for session cookies *)
1717- same_site : same_site option; (** Same-site policy *)
1818- creation_time : Ptime.t; (** When cookie was created *)
1919- last_access : Ptime.t; (** Last time cookie was accessed *)
2020-}
2121-2222-(** Cookie jar for storing and managing cookies *)
2323-type t
2424-2525-(** {1 Creation and Loading} *)
2626-2727-(** Create an empty cookie jar *)
2828-val create : unit -> t
2929-3030-(** Load cookies from Mozilla format file.
3131- If xdg is provided, uses XDG data directory, otherwise uses provided path. *)
3232-val load : ?xdg:Xdge.t -> ?path:Eio.Fs.dir_ty Path.t -> unit -> t
3333-3434-(** Save cookies to Mozilla format file.
3535- If xdg is provided, uses XDG data directory, otherwise uses provided path. *)
3636-val save : ?xdg:Xdge.t -> ?path:Eio.Fs.dir_ty Path.t -> t -> unit
3737-3838-(** {1 Cookie Management} *)
3939-4040-(** Add a cookie to the jar *)
4141-val add_cookie : t -> cookie -> unit
4242-4343-(** Extract cookies from Set-Cookie headers *)
4444-val extract_from_headers : t -> url:string -> Headers.t -> unit
4545-4646-(** Get cookies applicable for a URL *)
4747-val get_cookies : t -> url:string -> cookie list
4848-4949-(** Add Cookie header for a request *)
5050-val add_to_headers : t -> url:string -> Headers.t -> Headers.t
5151-5252-(** Clear all cookies *)
5353-val clear : t -> unit
5454-5555-(** Clear expired cookies *)
5656-val clear_expired : t -> clock:_ Time.clock -> unit
5757-5858-(** Clear session cookies (those without expiry) *)
5959-val clear_session_cookies : t -> unit
6060-6161-(** Get the number of cookies in the jar *)
6262-val count : t -> int
6363-6464-(** {1 Cookie Creation} *)
6565-6666-(** Parse Set-Cookie header value into a cookie *)
6767-val parse_set_cookie : url:string -> string -> cookie option
6868-6969-(** Create cookie header value from cookies *)
7070-val make_cookie_header : cookie list -> string
7171-7272-(** {1 Pretty Printing} *)
7373-7474-(** Pretty print a cookie *)
7575-val pp_cookie : Format.formatter -> cookie -> unit
7676-7777-(** Pretty print a cookie jar *)
7878-val pp : Format.formatter -> t -> unit
7979-8080-(** {1 Mozilla Format} *)
8181-8282-(** Mozilla cookies.txt format:
8383- # Netscape HTTP Cookie File
8484- # This is a generated file! Do not edit.
8585-8686- domain include_subdomains path secure expires name value
8787-8888- Where:
8989- - domain: The domain that created the cookie
9090- - include_subdomains: TRUE if cookie applies to subdomains, FALSE otherwise
9191- - path: The path the cookie is valid for
9292- - secure: TRUE if cookie requires secure connection
9393- - expires: Unix timestamp when cookie expires (0 for session cookies)
9494- - name: Cookie name
9595- - value: Cookie value
9696-9797- Example:
9898- .github.com TRUE / TRUE 1735689600 _gh_sess abc123... *)
9999-100100-(** Write cookies in Mozilla format *)
101101-val to_mozilla_format : t -> string
102102-103103-(** Parse Mozilla format cookies *)
104104-val from_mozilla_format : string -> t
···1212module Status = Status
1313module Error = Error
1414module Session = Session
1515-module Cookie_jar = Cookie_jar
1615module Retry = Retry
+1-4
stack/requests/lib/requests.mli
···135135(** Stateful HTTP sessions with cookies and configuration persistence *)
136136module Session = Session
137137138138-(** Cookie storage and management *)
139139-module Cookie_jar = Cookie_jar
140140-141138(** Retry policies and backoff strategies *)
142139module Retry = Retry
143140···183180module Mime = Mime
184181185182(** Timeout configuration for requests *)
186186-module Timeout = Timeout183183+module Timeout = Timeout
+47-14
stack/requests/lib/session.ml
···3333 sw : Eio.Switch.t;
3434 client : ('clock, 'net) Client.t;
3535 clock : 'clock;
3636- cookie_jar : Cookie_jar.t;
3636+ cookie_jar : Cookeio.jar;
3737 mutable default_headers : Headers.t;
3838 mutable auth : Auth.t option;
3939 mutable timeout : Timeout.t;
···9191 | Some jar, _, _ -> jar
9292 | None, true, Some xdg_ctx ->
9393 Log.debug (fun m -> m "Loading persistent cookie jar from XDG data dir");
9494- Cookie_jar.load ~xdg:xdg_ctx ()
9494+ let data_dir = Xdge.data_dir xdg_ctx in
9595+ let cookie_file = Eio.Path.(data_dir / "cookies.txt") in
9696+ Cookeio.load cookie_file
9597 | None, _, _ ->
9696- Cookie_jar.create ()
9898+ Cookeio.create ()
9799 in
9810099101 let session = {
···120122 Log.info (fun m -> m "Closing session after %d requests" session.requests_made);
121123 if persist_cookies && Option.is_some xdg then begin
122124 Log.info (fun m -> m "Saving cookies on session close");
123123- Cookie_jar.save ?xdg session.cookie_jar
125125+ let data_dir = Xdge.data_dir (Option.get xdg) in
126126+ let cookie_file = Eio.Path.(data_dir / "cookies.txt") in
127127+ Cookeio.save cookie_file session.cookie_jar
124128 end
125129 );
126130···128132129133let save_cookies : ('a, 'b) t -> unit = fun t ->
130134 if t.persist_cookies && Option.is_some t.xdg then
131131- Cookie_jar.save ?xdg:t.xdg t.cookie_jar
135135+ let data_dir = Xdge.data_dir (Option.get t.xdg) in
136136+ let cookie_file = Eio.Path.(data_dir / "cookies.txt") in
137137+ Cookeio.save cookie_file t.cookie_jar
132138133139let load_cookies : ('a, 'b) t -> unit = fun t ->
134140 if t.persist_cookies && Option.is_some t.xdg then
135135- let loaded = Cookie_jar.load ?xdg:t.xdg () in
141141+ let data_dir = Xdge.data_dir (Option.get t.xdg) in
142142+ let cookie_file = Eio.Path.(data_dir / "cookies.txt") in
143143+ let loaded = Cookeio.load cookie_file in
136144 (* Copy loaded cookies into our jar *)
137137- Cookie_jar.clear t.cookie_jar;
138138- let cookies_from_loaded = Cookie_jar.to_mozilla_format loaded in
139139- let _reloaded = Cookie_jar.from_mozilla_format cookies_from_loaded in
145145+ Cookeio.clear t.cookie_jar;
146146+ let cookies_from_loaded = Cookeio.to_mozilla_format loaded in
147147+ let _reloaded = Cookeio.from_mozilla_format cookies_from_loaded in
140148 (* This is a bit convoluted but maintains the same jar reference *)
141149 ()
142150···172180let cookies t = t.cookie_jar
173181174182let clear_cookies t =
175175- Cookie_jar.clear t.cookie_jar
183183+ Cookeio.clear t.cookie_jar
176184177185(** {1 Internal Request Function} *)
178186···183191 let headers =
184192 t.default_headers
185193 |> Headers.merge (Option.value headers ~default:Headers.empty)
186186- |> Cookie_jar.add_to_headers t.cookie_jar ~url
194194+ |> (fun headers ->
195195+ let uri = Uri.of_string url in
196196+ let domain = Uri.host_with_default ~default:"localhost" uri in
197197+ let path = Uri.path uri in
198198+ let is_secure = Uri.scheme uri = Some "https" in
199199+ let cookies = Cookeio.get_cookies t.cookie_jar ~domain ~path ~is_secure in
200200+ if cookies = [] then headers
201201+ else
202202+ let cookie_header = Cookeio.make_cookie_header cookies in
203203+ Headers.add "cookie" cookie_header headers)
187204 in
188205189206 (* Use provided auth or session default *)
···224241 in
225242226243 (* Extract cookies from response *)
227227- Cookie_jar.extract_from_headers t.cookie_jar ~url (Response.headers response);
244244+ let uri = Uri.of_string url in
245245+ let domain = Uri.host_with_default ~default:"localhost" uri in
246246+ let path =
247247+ let p = Uri.path uri in
248248+ if p = "" then "/"
249249+ else
250250+ let last_slash = String.rindex_opt p '/' in
251251+ match last_slash with
252252+ | None -> "/"
253253+ | Some i -> String.sub p 0 (i + 1)
254254+ in
255255+ let set_cookie_values = Headers.get_multi "set-cookie" (Response.headers response) in
256256+ List.iter (fun value ->
257257+ match Cookeio.parse_set_cookie ~domain ~path value with
258258+ | Some cookie -> Cookeio.add_cookie t.cookie_jar cookie
259259+ | None -> Log.warn (fun m -> m "Failed to parse Set-Cookie header: %s" value)
260260+ ) set_cookie_values;
228261229262 (* Update statistics *)
230263 Mutex.lock t.mutex;
···293326let pp ppf t =
294327 Mutex.lock t.mutex;
295328 let stats = t.requests_made, t.total_time,
296296- Cookie_jar.count t.cookie_jar in
329329+ Cookeio.count t.cookie_jar in
297330 Mutex.unlock t.mutex;
298331 let requests, time, cookies = stats in
299332 Format.fprintf ppf "@[<v>Session:@,\
···321354 let result = Stats.{
322355 requests_made = t.requests_made;
323356 total_time = t.total_time;
324324- cookies_count = Cookie_jar.count t.cookie_jar;
357357+ cookies_count = Cookeio.count t.cookie_jar;
325358 retries_count = t.retries_count;
326359 } in
327360 Mutex.unlock t.mutex;
+2-2
stack/requests/lib/session.mli
···6060val create :
6161 sw:Eio.Switch.t ->
6262 ?client:('clock Eio.Time.clock,'net Eio.Net.t) Client.t ->
6363- ?cookie_jar:Cookie_jar.t ->
6363+ ?cookie_jar:Cookeio.jar ->
6464 ?default_headers:Headers.t ->
6565 ?auth:Auth.t ->
6666 ?timeout:Timeout.t ->
···113113114114(** {1 Cookie Management} *)
115115116116-val cookies : ('clock, 'net) t -> Cookie_jar.t
116116+val cookies : ('clock, 'net) t -> Cookeio.jar
117117(** Get the session's cookie jar for direct manipulation *)
118118119119val clear_cookies : ('clock, 'net) t -> unit