Skip to content

Commit 7c6519b

Browse files
committed
eio(client): Client.read_fixed take_all
RFC https://www.rfc-editor.org/rfc/rfc7230#section-3.3.3 point 7 states that responses with missing Content-Length/Transfer-Encoding headers should read the message body until the end of file. This commit implements the above spec. Since now that read_fixed is different in client and server, we also remove it from the Body module.
1 parent 67089da commit 7c6519b

File tree

7 files changed

+26
-25
lines changed

7 files changed

+26
-25
lines changed

cohttp-eio/examples/client1.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ let () =
1313
Eio_main.run @@ fun env ->
1414
Switch.run @@ fun sw ->
1515
let res = Client.get (conn env sw) "/" in
16-
match Client.read_fixed res with Some b -> print_string b | None -> ()
16+
print_string @@ Client.read_fixed res

cohttp-eio/examples/docker_client.ml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ let () =
2020
Printf.printf "Response code: %d\n" code;
2121
Printf.printf "Headers: %s\n"
2222
(fst res |> Response.headers |> Http.Header.to_string);
23-
match Client.read_fixed res with
24-
| Some body ->
25-
Printf.printf "Body of length: %d\n" (String.length body);
26-
print_endline ("Received body\n" ^ body)
27-
| None -> ()
23+
let body = Client.read_fixed res in
24+
Printf.printf "Body of length: %d\n" (String.length body);
25+
print_endline ("Received body\n" ^ body)

cohttp-eio/src/body.ml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ let pp_chunk fmt = function
4545
fmt chunk
4646
| Last_chunk extensions -> pp_chunk_extension fmt extensions
4747

48-
let read_fixed t headers =
49-
let ( let* ) o f = Option.bind o f in
50-
let ( let+ ) o f = Option.map f o in
51-
let* v = Http.Header.get headers "Content-Length" in
52-
let+ content_length = int_of_string_opt v in
53-
Buf_read.take content_length t
54-
5548
(* Chunked encoding parser *)
5649

5750
let hex_digit = function

cohttp-eio/src/client.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ let response buf_read =
6363

6464
let call ?(meth = `GET) ?(version = `HTTP_1_1) ?(headers = Http.Header.init ())
6565
?(body = Body.Empty) conn_fn uri =
66-
let (resource_path, (host_name, host_port), flow) = conn_fn uri in
66+
let resource_path, (host_name, host_port), flow = conn_fn uri in
6767
let host =
6868
match host_port with
6969
| Some port -> host_name ^ ":" ^ string_of_int port
@@ -103,7 +103,13 @@ let patch ?version ?headers ?body stream uri =
103103
(* Response Body *)
104104

105105
let read_fixed ((response, reader) : Http.Response.t * Buf_read.t) =
106-
Body.read_fixed reader response.headers
106+
match
107+
Option.bind
108+
(Http.Header.get response.headers "Content-Length")
109+
int_of_string_opt
110+
with
111+
| Some content_length -> Buf_read.take content_length reader
112+
| None -> Buf_read.take_all reader
107113

108114
let read_chunked : response -> (Body.chunk -> unit) -> Http.Header.t option =
109115
fun (response, reader) f -> Body.read_chunked reader response.headers f

cohttp-eio/src/cohttp_eio.mli

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,11 @@ module Client : sig
160160

161161
(** {1 Response Body} *)
162162

163-
val read_fixed : response -> string option
164-
(** [read_fixed (response,reader)] is [Some bytes], where [bytes] is of length
165-
[n] if "Content-Length" header is a valid integer value [n] in [response].
166-
[reader] is updated to reflect that [n] bytes was read. *)
163+
val read_fixed : response -> string
164+
(** [read_fixed (response,reader)] is [body_content], where [body_content] is
165+
of length [n] if "Content-Length" header exists and is a valid integer
166+
value [n] in [response]. Otherwise [body_content] holds all bytes until
167+
eof. *)
167168

168169
val read_chunked : response -> (Body.chunk -> unit) -> Http.Header.t option
169170
(** [read_chunked response chunk_handler] is [Some updated_headers] if

cohttp-eio/src/server.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ let domain_count =
1616

1717
let read_fixed request reader =
1818
match Http.Request.meth request with
19-
| `POST | `PUT | `PATCH -> Body.read_fixed reader request.headers
19+
| `POST | `PUT | `PATCH ->
20+
let ( let* ) o f = Option.bind o f in
21+
let ( let+ ) o f = Option.map f o in
22+
let* v = Http.Header.get request.headers "Content-Length" in
23+
let+ content_length = int_of_string_opt v in
24+
Buf_read.take content_length reader
2025
| _ -> None
2126

2227
let read_chunked request reader f =

cohttp-eio/tests/test_client.ml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let get env sw port =
1515
~headers:(Http.Header.of_list [ ("Accept", "application/json") ])
1616
(conn env sw port) "/get"
1717
in
18-
match Client.read_fixed res with Some s -> print_string s | None -> ()
18+
print_string @@ Client.read_fixed res
1919

2020
let post env sw port =
2121
let content = "hello world!" in
@@ -29,7 +29,7 @@ let post env sw port =
2929
])
3030
~body:(Body.Fixed content) (conn env sw port) "/post"
3131
in
32-
match Client.read_fixed res with Some s -> print_string s | None -> ()
32+
print_string @@ Client.read_fixed res
3333

3434
(** Write chunk test.
3535
@@ -82,9 +82,7 @@ let post_chunk env sw port =
8282
(Body.Chunked { body_writer = body_writer chan 0; trailer_writer })
8383
(conn env sw port) "/handle_chunk")
8484
|> Client.read_fixed
85-
|> function
86-
| Some r -> print_string r
87-
| None -> ()
85+
|> print_string
8886

8987
(* Read chunk and dump to a "client_chunks2.txt" *)
9088
let get_chunk env sw port =

0 commit comments

Comments
 (0)