mirage / ocaml-cohttp

An OCaml library for HTTP clients and servers using Lwt or Async
Other
704 stars 174 forks source link

cohttp-eio: client: use permissive argument type for make_generic #1026

Closed ushitora-anqou closed 5 months ago

ushitora-anqou commented 6 months ago

Currently, Cohttp_eio.Client.makegeneric takes a function that returns a value of type ` Eio.Net.stream_socketas an argument. This type is too strict and can be relaxed toEio.Flow.two_way_ty r`. The difference between these two types is actually important when we use cohttp-eio with ocaml-tls. Consider the following code:

let authenticator = Ca_certs.authenticator () |> Result.get_ok

let connect_via_tls url socket =
  let tls_config = Tls.Config.client ~authenticator () in
  let host =
    Uri.host url
    |> Option.map (fun x -> Domain_name.(host_exn (of_string_exn x)))
  in
  Tls_eio.client_of_flow ?host tls_config socket

let connect net ~sw url =
  (* NOTE: Do something different than `Cohttp_eio.Client.tcp_address` here and get `addr` *)
  let socket = Eio.Net.connect ~sw net addr in
  connect_via_tls url socket

let () =
  Eio_main.run @@ fun env ->
  Cohttp_eio.Client.make_generic (fun ~sw url ->
      let flow = connect (Eio.Stdenv.net env) ~sw url in
      flow (* <<---- TYPE ERROR HERE!

Error: This expression has type
         Tls_eio.t = [ `Flow | `R | `Shutdown | `Tls | `W ] Eio_unix.source
       but an expression was expected of type
         [> [> `Generic ] Eio.Net.stream_socket_ty ] Eio_unix.source
       Type [ `Flow | `R | `Shutdown | `Tls | `W ] is not compatible with type
         [> ([> `Generic ] as 'a) Eio.Net.stream_socket_ty ] =
           [> `Close
            | `Flow
            | `Platform of 'a
            | `R
            | `Shutdown
            | `Socket
            | `Stream
            | `W ]
       The first variant type does not allow tag(s)
       `Close, `Platform, `Socket, `Stream
*))

This code won't compile if make_generic expects _ Eio.Net.stream_socket, but it will compile if Eio.Flow.two_way_ty r.

This patch solves the above problem by changing the interface of make_generic to (sw:Switch.t -> Uri.t -> Eio.Flow.two_way_ty r) -> t. The implementation of make_generic is effectively an identity function, so we don't need to change the implementation.