Skip to content

Commit

Permalink
eio(client): Client.call expects conn, host and resource_path as para…
Browse files Browse the repository at this point in the history
…mters
  • Loading branch information
bikallem committed Aug 25, 2022
1 parent 7c6519b commit 09c2d01
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 78 deletions.
13 changes: 5 additions & 8 deletions cohttp-eio/examples/client1.ml
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
open Eio
open Cohttp_eio

let conn env sw resource_path =
let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let hostname, port = ("www.example.org", 80) in
let he = Unix.gethostbyname hostname in
let addr = `Tcp (Eio_unix.Ipaddr.of_unix he.h_addr_list.(0), port) in
let flow = Net.connect ~sw env#net addr in
let conn = Net.connect ~sw env#net addr in
let host = (hostname, Some port) in
(resource_path, host, flow)

let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let res = Client.get (conn env sw) "/" in
let res = Client.get ~conn host "/" in
print_string @@ Client.read_fixed res
11 changes: 3 additions & 8 deletions cohttp-eio/examples/docker_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@ module Client = Cohttp_eio.Client
module Response = Http.Response
module Status = Http.Status

let conn env sw resource_path =
let hostname = "docker" in
let addr = `Unix "/var/run/docker.sock" in
let flow = Net.connect ~sw env#net addr in
let host = (hostname, None) in
(resource_path, host, flow)

let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let res = Client.get (conn env sw) "/version" in
let addr = `Unix "/var/run/docker.sock" in
let conn = Net.connect ~sw env#net addr in
let res = Client.get ~conn ("docker", None) "/version" in
let code = fst res |> Response.status |> Status.to_int in
Printf.printf "Response code: %d\n" code;
Printf.printf "Headers: %s\n"
Expand Down
52 changes: 26 additions & 26 deletions cohttp-eio/src/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ module Buf_write = Eio.Buf_write
type response = Http.Response.t * Buf_read.t
type host = string * int option
type resource_path = string
type ('a, 'b) conn = 'a -> (resource_path * host * #Eio.Flow.two_way as 'b)

type ('a, 'b) body_disallowed_call =
type 'a body_disallowed_call =
?version:Http.Version.t ->
?headers:Http.Header.t ->
('a, 'b) conn ->
'a ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response
(** [body_disallowed_call] denotes HTTP client calls where a request is not
allowed to have a request body. *)

type ('a, 'b) body_allowed_call =
type 'a body_allowed_call =
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Body.t ->
('a, 'b) conn ->
'a ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response

(* Request line https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1 *)
Expand Down Expand Up @@ -62,43 +63,42 @@ let response buf_read =
(* Generic HTTP call *)

let call ?(meth = `GET) ?(version = `HTTP_1_1) ?(headers = Http.Header.init ())
?(body = Body.Empty) conn_fn uri =
let resource_path, (host_name, host_port), flow = conn_fn uri in
?(body = Body.Empty) ~conn host resource_path =
let host =
match host_port with
| Some port -> host_name ^ ":" ^ string_of_int port
| None -> host_name
match host with
| host, Some port -> host ^ ":" ^ string_of_int port
| host, None -> host
in
Buf_write.with_flow ~initial_size:0x1000 flow (fun writer ->
Buf_write.with_flow ~initial_size:0x1000 conn (fun writer ->
let headers = Http.Header.add_unless_exists headers "Host" host in
write_request writer (meth, version, headers, resource_path, body);
let reader =
Eio.Buf_read.of_flow ~initial_size:0x1000 ~max_size:max_int flow
Eio.Buf_read.of_flow ~initial_size:0x1000 ~max_size:max_int conn
in
let response = response reader in
(response, reader))

(* HTTP Calls with Body Disallowed *)

let get ?version ?headers conn_fn uri =
call ~meth:`GET ?version ?headers conn_fn uri
let get ?version ?headers ~conn host resource_path =
call ~meth:`GET ?version ?headers ~conn host resource_path

let head ?version ?headers stream uri =
call ~meth:`HEAD ?version ?headers stream uri
let head ?version ?headers ~conn host resource_path =
call ~meth:`HEAD ?version ?headers ~conn host resource_path

let delete ?version ?headers stream uri =
call ~meth:`DELETE ?version ?headers stream uri
let delete ?version ?headers ~conn host resource_path =
call ~meth:`DELETE ?version ?headers ~conn host resource_path

(* HTTP Calls with Body Allowed *)

let post ?version ?headers ?body stream uri =
call ~meth:`POST ?version ?headers ?body stream uri
let post ?version ?headers ?body ~conn host resource_path =
call ~meth:`POST ?version ?headers ?body ~conn host resource_path

let put ?version ?headers ?body stream uri =
call ~meth:`PUT ?version ?headers ?body stream uri
let put ?version ?headers ?body ~conn host resource_path =
call ~meth:`PUT ?version ?headers ?body ~conn host resource_path

let patch ?version ?headers ?body stream uri =
call ~meth:`PATCH ?version ?headers ?body stream uri
let patch ?version ?headers ?body ~conn host resource_path =
call ~meth:`PATCH ?version ?headers ?body ~conn host resource_path

(* Response Body *)

Expand Down
36 changes: 18 additions & 18 deletions cohttp-eio/src/cohttp_eio.mli
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ module Server : sig
val not_found_handler : handler
end

(** [Client] is a HTTP/1.1 client. *)
module Client : sig
type response = Http.Response.t * Eio.Buf_read.t

Expand All @@ -112,25 +113,23 @@ module Client : sig
(** Represents HTTP request resource path, e.g. "/shop/purchase",
"/shop/items", "/shop/categories/" etc. *)

type ('a, 'b) conn = 'a -> (resource_path * host * #Eio.Flow.two_way as 'b)
(** [('a, 'b conn)] is [(resource_path, host, flow)]. [flow] is the Eio flow
value which is connected to the [host]. *)

type ('a, 'b) body_disallowed_call =
type 'a body_disallowed_call =
?version:Http.Version.t ->
?headers:Http.Header.t ->
('a, 'b) conn ->
'a ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response
(** [body_disallowed_call] denotes HTTP client calls where a request is not
allowed to have a request body. *)

type ('a, 'b) body_allowed_call =
type 'a body_allowed_call =
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Body.t ->
('a, 'b) conn ->
'a ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response
(** [body_allowed_call] denotes HTTP client calls where a request can
optionally have a request body. *)
Expand All @@ -142,21 +141,22 @@ module Client : sig
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Body.t ->
('a, 'b) conn ->
'a ->
conn:#Eio.Flow.two_way ->
host ->
resource_path ->
response

(** {1 HTTP Calls with Body Disallowed} *)

val get : ('a, 'b) body_disallowed_call
val head : ('a, 'b) body_disallowed_call
val delete : ('a, 'b) body_disallowed_call
val get : 'a body_disallowed_call
val head : 'a body_disallowed_call
val delete : 'a body_disallowed_call

(** {1 HTTP Calls with Body Allowed} *)

val post : ('a, 'b) body_allowed_call
val put : ('a, 'b) body_allowed_call
val patch : ('a, 'b) body_allowed_call
val post : 'a body_allowed_call
val put : 'a body_allowed_call
val patch : 'a body_allowed_call

(** {1 Response Body} *)

Expand Down
33 changes: 15 additions & 18 deletions cohttp-eio/tests/test_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,15 @@ module Stdenv = Eio.Stdenv
module Switch = Eio.Switch
open Cohttp_eio

let conn env sw port resource_path =
let addr = `Tcp (Net.Ipaddr.V4.loopback, port) in
let flow = Net.connect ~sw env#net addr in
let host = ("localhost", Some port) in
(resource_path, host, flow)

let get env sw port =
let get conn host =
let res =
Client.get
~headers:(Http.Header.of_list [ ("Accept", "application/json") ])
(conn env sw port) "/get"
~conn host "/get"
in
print_string @@ Client.read_fixed res

let post env sw port =
let post conn host =
let content = "hello world!" in
let content_length = String.length content |> string_of_int in
let res =
Expand All @@ -27,7 +21,7 @@ let post env sw port =
[
("Accept", "application/json"); ("Content-Length", content_length);
])
~body:(Body.Fixed content) (conn env sw port) "/post"
~body:(Body.Fixed content) ~conn host "/post"
in
print_string @@ Client.read_fixed res

Expand All @@ -36,7 +30,7 @@ let post env sw port =
Read from text file "chunks.txt" and write each line as a chunk. We add some
chunk extensions to the first chunk. This is purely for demonstrative effect
and for testing purposes rather than for any such specific requirement. *)
let post_chunk env sw port =
let post_chunk conn host =
let rec body_writer chan chunks f =
match In_channel.input_line chan with
| Some data ->
Expand Down Expand Up @@ -80,17 +74,17 @@ let post_chunk env sw port =
])
~body:
(Body.Chunked { body_writer = body_writer chan 0; trailer_writer })
(conn env sw port) "/handle_chunk")
~conn host "/handle_chunk")
|> Client.read_fixed
|> print_string

(* Read chunk and dump to a "client_chunks2.txt" *)
let get_chunk env sw port =
let get_chunk env conn host =
let write_chunk_to_file flow chunk =
let data = Format.asprintf "%a\n\n" Body.pp_chunk chunk in
Eio.Flow.copy_string data flow
in
let res = Client.get (conn env sw port) "/get_chunk" in
let res = Client.get ~conn host "/get_chunk" in
let path = Eio.Path.(Stdenv.cwd env / "client_chunks2.txt") in
Eio.Path.with_open_out ~append:false ~create:(`Or_truncate 0o666) path
(fun flow ->
Expand All @@ -114,9 +108,12 @@ let () =

Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
let addr = `Tcp (Net.Ipaddr.V4.loopback, !port) in
let conn = Net.connect ~sw env#net addr in
let host = ("localhost", Some !port) in
match !t with
| "get" -> get env sw !port
| "post" -> post env sw !port
| "post_chunk" -> post_chunk env sw !port
| "get_chunk" -> get_chunk env sw !port
| "get" -> get conn host
| "post" -> post conn host
| "post_chunk" -> post_chunk conn host
| "get_chunk" -> get_chunk env conn host
| _ -> print_string "Usage: test-client [get|post]"

0 comments on commit 09c2d01

Please sign in to comment.