server: use available buffer when writing body with chunk encoding

there's already a buffer nearby, we can use it to write streams/writer
bodies to the output channel
This commit is contained in:
Simon Cruanes 2023-07-18 15:39:09 -04:00
parent 098bf10466
commit e3d8cf9fdd
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
3 changed files with 16 additions and 10 deletions

View file

@ -480,7 +480,7 @@ module Response = struct
k "output response: %s" k "output response: %s"
(Format.asprintf "%a" pp { self with body = `String "<...>" })); (Format.asprintf "%a" pp { self with body = `String "<...>" }));
(* write headers *) (* write headers, using [buf] to batch writes *)
List.iter List.iter
(fun (k, v) -> (fun (k, v) ->
Printf.bprintf tmp_buffer "%s: %s\r\n" k v; Printf.bprintf tmp_buffer "%s: %s\r\n" k v;
@ -490,12 +490,16 @@ module Response = struct
IO.Out_channel.output_buf oc buf; IO.Out_channel.output_buf oc buf;
IO.Out_channel.output_string oc "\r\n"; IO.Out_channel.output_string oc "\r\n";
(* flush after writing headers *)
IO.Out_channel.flush oc;
Buf.clear buf;
(match body with (match body with
| `String "" | `Void -> () | `String "" | `Void -> ()
| `String s -> IO.Out_channel.output_string oc s | `String s -> IO.Out_channel.output_string oc s
| `Writer w -> | `Writer w ->
let oc' = IO.Out_channel.chunk_encoding ~close_rec:false oc in (* use buffer to chunk encode [w] *)
let oc' = IO.Out_channel.chunk_encoding ~buf ~close_rec:false oc in
(try (try
IO.Writer.write oc' w; IO.Writer.write oc' w;
IO.Out_channel.close oc' IO.Out_channel.close oc'
@ -504,7 +508,7 @@ module Response = struct
raise e) raise e)
| `Stream str -> | `Stream str ->
(try (try
Byte_stream.output_chunked' oc str; Byte_stream.output_chunked' ~buf oc str;
Byte_stream.close str Byte_stream.close str
with e -> with e ->
Byte_stream.close str; Byte_stream.close str;

View file

@ -299,11 +299,11 @@ let read_chunked ?(buf = Buf.create ()) ~fail (bs : t) : t =
refill := false) refill := false)
() ()
let output_chunked' (oc : IO.Out_channel.t) (self : t) : unit = let output_chunked' ?buf (oc : IO.Out_channel.t) (self : t) : unit =
let oc' = IO.Out_channel.chunk_encoding oc ~close_rec:false in let oc' = IO.Out_channel.chunk_encoding ?buf oc ~close_rec:false in
to_chan' oc' self; to_chan' oc' self;
IO.Out_channel.close oc' IO.Out_channel.close oc'
(* print a stream as a series of chunks *) (* print a stream as a series of chunks *)
let output_chunked (oc : out_channel) (self : t) : unit = let output_chunked ?buf (oc : out_channel) (self : t) : unit =
output_chunked' (IO.Out_channel.of_out_channel oc) self output_chunked' ?buf (IO.Out_channel.of_out_channel oc) self

View file

@ -149,9 +149,11 @@ val read_exactly :
@param too_short is called if [bs] closes with still [n] bytes remaining @param too_short is called if [bs] closes with still [n] bytes remaining
*) *)
val output_chunked : out_channel -> t -> unit val output_chunked : ?buf:Tiny_httpd_buf.t -> out_channel -> t -> unit
(** Write the stream into the channel, using the chunked encoding. *) (** Write the stream into the channel, using the chunked encoding.
@param buf optional buffer for chunking (since NEXT_RELEASE) *)
val output_chunked' : Tiny_httpd_io.Out_channel.t -> t -> unit val output_chunked' :
?buf:Tiny_httpd_buf.t -> Tiny_httpd_io.Out_channel.t -> t -> unit
(** Write the stream into the channel, using the chunked encoding. (** Write the stream into the channel, using the chunked encoding.
@since NEXT_RELEASE *) @since NEXT_RELEASE *)