Timeout Cohttprequests

Not sure if this is better suited for StackOverflow or this site, but thought I’d post here to start with.

I see on the server-side of things there’s https://github.com/mirage/ocaml-cohttp/blob/e9c29aec81a1850bc1574684d27ea2ffa6609264/cohttp-lwt-unix/src/server.mli#L13 - but I also see a TODO item to test it.

But for the client side, I’m looking for a way with Cohhtp.Client to make sure a network request doesn’t take longer than n milliseconds.

1 Like

You can use Lwt.pick or Lwt_unix.with_timeout for this. An example using Lwt.pick:

let get_or_timeout ?(max_request_duration = max_float) uri =
  let open Lwt.Infix in
  let timeout =
    Lwt_unix.sleep max_request_duration >>= fun () ->
    Lwt.return_error `Timed_out
  in
  let get =
    Cohttp_lwt_unix.Client.get uri >>= fun response ->
    Lwt.return_ok response
  in
  Lwt.pick [
    timeout;
    get;
  ]

with type

val get_or_timeout : (Cohttp.Response.t * Cohttp_lwt_body.t, [> `Timed_out ]) result

If the timeout promise finishes first the get promise will be canceled. If the get promise finishes first then the timeout promise will be canceled.

1 Like

Here’s the version of Async:

let timeout_send2 url timeout =
  let aux url timeout =  
    let uri = Uri.of_string url in
    let%bind _, body = Cohttp_async.Client.get ~interrupt:(after (sec timeout)) uri in
    Body.to_string body    
  in
  Clock.with_timeout (sec timeout) (aux url timeout)
  >>| function
  | `Result body -> Log.debug logger "body: %s" body
  | `Timeout  -> Log.debug logger "Timeout with url:%s" url