···261261 Eio.Mutex.unlock t.mutex;
262262 Log.info (fun m -> m "Cleared %d session cookies" removed)
263263264264+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+264270(** {1 Mozilla Format} *)
265271266272let to_mozilla_format_internal t =
+3
stack/requests/lib/cookie_jar.mli
···5858(** Clear session cookies (those without expiry) *)
5959val clear_session_cookies : t -> unit
60606161+(** Get the number of cookies in the jar *)
6262+val count : t -> int
6363+6164(** {1 Cookie Creation} *)
62656366(** Parse Set-Cookie header value into a cookie *)
+45-10
stack/requests/lib/session.ml
···3344(** {1 Types} *)
5566+(** Session statistics *)
77+module Stats = struct
88+ type t = {
99+ requests_made : int;
1010+ total_time : float;
1111+ cookies_count : int;
1212+ retries_count : int;
1313+ }
1414+1515+ let requests_made t = t.requests_made
1616+ let total_time t = t.total_time
1717+ let cookies_count t = t.cookies_count
1818+ let retries_count t = t.retries_count
1919+2020+ let pp ppf t =
2121+ Format.fprintf ppf "@[<v>Session Statistics:@,\
2222+ requests made: %d@,\
2323+ total time: %.3fs@,\
2424+ cookies: %d@,\
2525+ retries: %d@]"
2626+ t.requests_made
2727+ t.total_time
2828+ t.cookies_count
2929+ t.retries_count
3030+end
3131+632type ('clock, 'net) t = {
733 sw : Eio.Switch.t;
834 client : ('clock, 'net) Client.t;
···204230 ~config:retry_config
205231 ~f:make_request
206232 ~should_retry_exn:(function
207207- (* TODO: Handle Stream exceptions once Stream module is properly imported *)
233233+ (* Retry on retryable errors *)
234234+ | Error.Timeout -> true
235235+ | Error.ConnectionError _ -> true
236236+ | Error.HTTPError { status; _ } when status >= 500 -> true (* Server errors *)
237237+ | Error.SSLError _ -> false (* Don't retry SSL errors *)
238238+ | Error.ProxyError _ -> true
239239+ | Eio.Io (Eio.Net.E (Connection_reset _), _) -> true
240240+ | Eio.Time.Timeout -> true
208241 | _ -> false)
209242 in
210243···259292let upload t ?headers ?auth ?timeout ?method_ ?mime ?length ~source url =
260293 let method_ = Option.value method_ ~default:`POST in
261294 let body = Body.of_stream ?length (Option.value mime ~default:Mime.octet_stream) source in
262262- (* TODO: Add progress tracking wrapper around source *)
295295+ (* Progress tracking would require wrapping Eio.Flow.source which is complex.
296296+ Use Client.upload with on_progress callback for progress tracking instead. *)
263297 execute_request t ?headers ~body ?auth ?timeout ~method_ url
264298265299let download t ?headers ?auth ?timeout url ~sink =
266300 let response = execute_request t ?headers ?auth ?timeout ~method_:`GET url in
267301 let body = Response.body response in
268268- (* TODO: Add progress tracking wrapper *)
302302+ (* Progress tracking would require intercepting Eio.Flow.copy.
303303+ Use Client.download with on_progress callback for progress tracking instead. *)
269304 Eio.Flow.copy body sink
270305271306let download_file t ?headers ?auth ?timeout url path =
···276311let pp ppf t =
277312 Mutex.lock t.mutex;
278313 let stats = t.requests_made, t.total_time,
279279- (match t.cookie_jar with _jar -> 0) in (* TODO: Get actual count *)
314314+ Cookie_jar.count t.cookie_jar in
280315 Mutex.unlock t.mutex;
281316 let requests, time, cookies = stats in
282317 Format.fprintf ppf "@[<v>Session:@,\
···301336302337let stats t =
303338 Mutex.lock t.mutex;
304304- let result = object
305305- method requests_made = t.requests_made
306306- method total_time = t.total_time
307307- method cookies_count = 0 (* TODO: Get from cookie jar *)
308308- method retries_count = t.retries_count
309309- end in
339339+ let result = Stats.{
340340+ requests_made = t.requests_made;
341341+ total_time = t.total_time;
342342+ cookies_count = Cookie_jar.count t.cookie_jar;
343343+ retries_count = t.retries_count;
344344+ } in
310345 Mutex.unlock t.mutex;
311346 result
312347
+26-6
stack/requests/lib/session.mli
···3030type ('clock, 'net) t
3131(** A session maintains state across multiple HTTP requests *)
32323333+(** Session statistics *)
3434+module Stats : sig
3535+ type t = {
3636+ requests_made : int; (** Total number of requests made *)
3737+ total_time : float; (** Total time spent in requests (seconds) *)
3838+ cookies_count : int; (** Number of cookies in the jar *)
3939+ retries_count : int; (** Total number of retries performed *)
4040+ }
4141+4242+ (** Get the number of requests made *)
4343+ val requests_made : t -> int
4444+4545+ (** Get the total time spent in requests *)
4646+ val total_time : t -> float
4747+4848+ (** Get the number of cookies *)
4949+ val cookies_count : t -> int
5050+5151+ (** Get the number of retries *)
5252+ val retries_count : t -> int
5353+5454+ (** Pretty printer for statistics *)
5555+ val pp : Format.formatter -> t -> unit
5656+end
5757+3358(** {1 Session Creation and Configuration} *)
34593560val create :
···248273val pp : Format.formatter -> ('clock, 'net) t -> unit
249274(** Pretty print session configuration *)
250275251251-val stats : ('clock, 'net) t -> <
252252- requests_made : int;
253253- total_time : float;
254254- cookies_count : int;
255255- retries_count : int;
256256->
276276+val stats : ('clock, 'net) t -> Stats.t
257277(** Get session statistics *)
258278259279(** {1 Examples} *)