Skip to content

Commit 06d5970

Browse files
committed
Add Body.to_string for converting entire bodies to strings
1 parent 3f2062d commit 06d5970

File tree

5 files changed

+19
-83
lines changed

5 files changed

+19
-83
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 0.10.1
22

33
* Accept a `(string * string) list` as http headers.
4+
* Add a `Body.to_string` for reading entire bodies as string.
45

56
# 0.10.0
67

README.md

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,6 @@ let httpbin_address =
9999

100100
If the incoming response's body fits entirely in the client's buffer Shuttle_http will represent the body as a fixed sized string, otherwise the body is read as an asynchronous stream so the response can be processed without having to wait for the entire body to arrive over the write.
101101

102-
We'll write a utility function that will convert a streaming response body to a string:
103-
104-
```ocaml
105-
let response_body_to_string response =
106-
let stream_to_string stream =
107-
let buffer = Buffer.create 128 in
108-
let%map () =
109-
Body.Stream.iter stream ~f:(fun chunk ->
110-
Buffer.add_string buffer chunk;
111-
Deferred.unit)
112-
in
113-
Buffer.contents buffer
114-
in
115-
match Response.body response with
116-
| Body.Empty -> return ""
117-
| Body.Fixed str -> return str
118-
| Body.Stream stream -> stream_to_string stream
119-
;;
120-
```
121-
122102
Shuttle_http offers a few different flavors of HTTP clients. The first one we'll see is a OneShot client. OneShot clients open a new TCP
123103
connection, send a HTTP Request, wait to receive a Response and then shut-down the TCP connection once the entire response has been consumed.
124104

@@ -133,7 +113,7 @@ let one_shot_client () =
133113
(Request.create `GET "/get")
134114
in
135115
printf "Response status: %d\n" (Response.status response |> Status.to_int);
136-
let%map body = response_body_to_string response in
116+
let%map body = Body.to_string (Response.body response) in
137117
print_endline body
138118
;;
139119
```

http/src/body.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,9 @@ let to_stream = function
7575
| Fixed x -> Stream.of_pipe (`Fixed (String.length x)) (Pipe.singleton x)
7676
| Stream x -> x
7777
;;
78+
79+
let to_string = function
80+
| Empty -> return ""
81+
| Fixed s -> return s
82+
| Stream x -> Stream.to_string x
83+
;;

http/src/body.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,7 @@ val stream : Stream.t -> t
7171

7272
(** [to_stream] converts a HTTP body to a stream. *)
7373
val to_stream : t -> Stream.t
74+
75+
(** [to_string] returns a deferred that will be fulfilled with the entire body converted
76+
to a string. *)
77+
val to_string : t -> string Deferred.t

http/test/test_http.ml

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,6 @@ let%expect_test "Keep-alives in clients" =
199199
(Client.Address.of_host_and_port
200200
(Host_and_port.create ~host:"localhost" ~port)))
201201
in
202-
let body_to_string response =
203-
let buf = Buffer.create 32 in
204-
let%map () =
205-
Body.Stream.iter
206-
(Body.to_stream (Response.body response))
207-
~f:(fun v ->
208-
Buffer.add_string buf v;
209-
Deferred.unit)
210-
in
211-
Buffer.contents buf
212-
in
213202
Monitor.protect
214203
~finally:(fun () -> Client.close client)
215204
(fun () ->
@@ -220,7 +209,7 @@ let%expect_test "Keep-alives in clients" =
220209
; headers = (Response.headers response : (string * string) list)
221210
; reason_phrase = (Response.reason_phrase response : string)
222211
}];
223-
let%bind body = body_to_string response in
212+
let%bind body = Body.to_string (Response.body response) in
224213
printf "\nBody: %S" body;
225214
[%expect
226215
{|
@@ -238,7 +227,7 @@ let%expect_test "Keep-alives in clients" =
238227
; headers = (Response.headers response : (string * string) list)
239228
; reason_phrase = (Response.reason_phrase response : string)
240229
}];
241-
let%map body = body_to_string response in
230+
let%map body = Body.to_string (Response.body response) in
242231
printf "\nBody: %S" body;
243232
[%expect
244233
{|
@@ -270,17 +259,6 @@ let%expect_test "No requests can be sent if a client is closed" =
270259
(Client.Address.of_host_and_port
271260
(Host_and_port.create ~host:"localhost" ~port)))
272261
in
273-
let body_to_string response =
274-
let buf = Buffer.create 32 in
275-
let%map () =
276-
Body.Stream.iter
277-
(Body.to_stream (Response.body response))
278-
~f:(fun v ->
279-
Buffer.add_string buf v;
280-
Deferred.unit)
281-
in
282-
Buffer.contents buf
283-
in
284262
Monitor.protect
285263
~finally:(fun () -> Client.close client)
286264
(fun () ->
@@ -291,7 +269,7 @@ let%expect_test "No requests can be sent if a client is closed" =
291269
; headers = (Response.headers response : (string * string) list)
292270
; reason_phrase = (Response.reason_phrase response : string)
293271
}];
294-
let%bind body = body_to_string response in
272+
let%bind body = Body.to_string (Response.body response) in
295273
printf "\nBody: %S" body;
296274
[%expect
297275
{|
@@ -319,17 +297,6 @@ let%expect_test "Clients are automatically closed if Connection:close header is
319297
(Client.Address.of_host_and_port
320298
(Host_and_port.create ~host:"localhost" ~port)))
321299
in
322-
let body_to_string response =
323-
let buf = Buffer.create 32 in
324-
let%map () =
325-
Body.Stream.iter
326-
(Body.to_stream (Response.body response))
327-
~f:(fun v ->
328-
Buffer.add_string buf v;
329-
Deferred.unit)
330-
in
331-
Buffer.contents buf
332-
in
333300
Monitor.protect
334301
~finally:(fun () -> Client.close client)
335302
(fun () ->
@@ -342,7 +309,7 @@ let%expect_test "Clients are automatically closed if Connection:close header is
342309
; headers = (Response.headers response : (string * string) list)
343310
; reason_phrase = (Response.reason_phrase response : string)
344311
}];
345-
let%bind body = body_to_string response in
312+
let%bind body = Body.to_string (Response.body response) in
346313
printf "\nBody: %S" body;
347314
[%expect
348315
{|
@@ -369,17 +336,6 @@ let%expect_test "Clients are automatically closed if Connection:close header is
369336
(Client.Address.of_host_and_port
370337
(Host_and_port.create ~host:"localhost" ~port)))
371338
in
372-
let body_to_string response =
373-
let buf = Buffer.create 32 in
374-
let%map () =
375-
Body.Stream.iter
376-
(Body.to_stream (Response.body response))
377-
~f:(fun v ->
378-
Buffer.add_string buf v;
379-
Deferred.unit)
380-
in
381-
Buffer.contents buf
382-
in
383339
Monitor.protect
384340
~finally:(fun () -> Client.close client)
385341
(fun () ->
@@ -390,7 +346,7 @@ let%expect_test "Clients are automatically closed if Connection:close header is
390346
; headers = (Response.headers response : (string * string) list)
391347
; reason_phrase = (Response.reason_phrase response : string)
392348
}];
393-
let%bind body = body_to_string response in
349+
let%bind body = Body.to_string (Response.body response) in
394350
printf "\nBody: %S" body;
395351
[%expect
396352
{|
@@ -420,17 +376,6 @@ let%expect_test "Persistent clients will re-connect if connection is closed" =
420376
(Client.Address.of_host_and_port
421377
(Host_and_port.create ~host:"localhost" ~port)))
422378
in
423-
let body_to_string response =
424-
let buf = Buffer.create 32 in
425-
let%map () =
426-
Body.Stream.iter
427-
(Body.to_stream (Response.body response))
428-
~f:(fun v ->
429-
Buffer.add_string buf v;
430-
Deferred.unit)
431-
in
432-
Buffer.contents buf
433-
in
434379
Monitor.protect
435380
~finally:(fun () -> Client.Persistent.close client)
436381
(fun () ->
@@ -443,7 +388,7 @@ let%expect_test "Persistent clients will re-connect if connection is closed" =
443388
; headers = (Response.headers response : (string * string) list)
444389
; reason_phrase = (Response.reason_phrase response : string)
445390
}];
446-
let%bind body = body_to_string response in
391+
let%bind body = Body.to_string (Response.body response) in
447392
printf "\nBody: %S" body;
448393
[%expect
449394
{|
@@ -464,7 +409,7 @@ let%expect_test "Persistent clients will re-connect if connection is closed" =
464409
; headers = (Response.headers response : (string * string) list)
465410
; reason_phrase = (Response.reason_phrase response : string)
466411
}];
467-
let%map body = body_to_string response in
412+
let%map body = Body.to_string (Response.body response) in
468413
printf "\nBody: %S" body;
469414
[%expect
470415
{|

0 commit comments

Comments
 (0)