add ?get_time_s param to create

This commit is contained in:
Simon Cruanes 2021-12-31 20:43:20 -05:00
parent e225212dba
commit 4aaa61f622
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6
2 changed files with 20 additions and 10 deletions

View file

@ -490,10 +490,10 @@ module Request = struct
) )
(* parse request, but not body (yet) *) (* parse request, but not body (yet) *)
let parse_req_start ~buf (bs:byte_stream) : unit t option resp_result = let parse_req_start ~get_time_s ~buf (bs:byte_stream) : unit t option resp_result =
try try
let line = Byte_stream.read_line ~buf bs in let line = Byte_stream.read_line ~buf bs in
let start_time = Unix.gettimeofday () in let start_time = get_time_s() in
let meth, path, version = let meth, path, version =
try try
let meth, path, version = Scanf.sscanf line "%s %s HTTP/1.%d\r" (fun x y z->x,y,z) in let meth, path, version = Scanf.sscanf line "%s %s HTTP/1.%d\r" (fun x y z->x,y,z) in
@ -566,8 +566,8 @@ module Request = struct
| e -> bad_reqf 500 "failed to read body: %s" (Printexc.to_string e) | e -> bad_reqf 500 "failed to read body: %s" (Printexc.to_string e)
module Internal_ = struct module Internal_ = struct
let parse_req_start ?(buf=Buf_.create()) bs = let parse_req_start ?(buf=Buf_.create()) ~get_time_s bs =
parse_req_start ~buf bs |> unwrap_resp_result parse_req_start ~get_time_s ~buf bs |> unwrap_resp_result
let parse_body ?(buf=Buf_.create()) req bs : _ t = let parse_body ?(buf=Buf_.create()) req bs : _ t =
parse_body_ ~tr_stream:(fun s->s) ~buf {req with body=bs} |> unwrap_resp_result parse_body_ ~tr_stream:(fun s->s) ~buf {req with body=bs} |> unwrap_resp_result
@ -577,7 +577,7 @@ end
(*$R (*$R
let q = "GET hello HTTP/1.1\r\nHost: coucou\r\nContent-Length: 11\r\n\r\nsalutationsSOMEJUNK" in let q = "GET hello HTTP/1.1\r\nHost: coucou\r\nContent-Length: 11\r\n\r\nsalutationsSOMEJUNK" in
let str = Byte_stream.of_string q in let str = Byte_stream.of_string q in
let r = Request.Internal_.parse_req_start str in let r = Request.Internal_.parse_req_start ~get_time_s:(fun _ -> 0.) str in
match r with match r with
| None -> assert_failure "should parse" | None -> assert_failure "should parse"
| Some req -> | Some req ->
@ -863,6 +863,8 @@ type t = {
buf_size: int; buf_size: int;
get_time_s : unit -> float;
mutable handler: (string Request.t -> Response.t); mutable handler: (string Request.t -> Response.t);
(* toplevel handler, if any *) (* toplevel handler, if any *)
@ -1006,6 +1008,7 @@ let create
?(max_connections=32) ?(max_connections=32)
?(timeout=0.0) ?(timeout=0.0)
?(buf_size=16 * 1_024) ?(buf_size=16 * 1_024)
?(get_time_s=Unix.gettimeofday)
?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t))) ?(new_thread=(fun f -> ignore (Thread.create f () : Thread.t)))
?(addr="127.0.0.1") ?(port=8080) ?sock ?(addr="127.0.0.1") ?(port=8080) ?sock
?(middlewares=[]) ?(middlewares=[])
@ -1015,7 +1018,7 @@ let create
let self = { let self = {
new_thread; addr; port; sock; masksigpipe; handler; buf_size; new_thread; addr; port; sock; masksigpipe; handler; buf_size;
running= true; sem_max_connections=Sem_.create max_connections; running= true; sem_max_connections=Sem_.create max_connections;
path_handlers=[]; timeout; path_handlers=[]; timeout; get_time_s;
middlewares=[]; middlewares_sorted=lazy []; middlewares=[]; middlewares_sorted=lazy [];
} in } in
List.iter (fun (stage,m) -> add_middleware self ~stage m) middlewares; List.iter (fun (stage,m) -> add_middleware self ~stage m) middlewares;
@ -1042,7 +1045,7 @@ let handle_client_ (self:t) (client_sock:Unix.file_descr) : unit =
let continue = ref true in let continue = ref true in
while !continue && self.running do while !continue && self.running do
_debug (fun k->k "read next request"); _debug (fun k->k "read next request");
match Request.parse_req_start ~buf is with match Request.parse_req_start ~get_time_s:self.get_time_s ~buf is with
| Ok None -> | Ok None ->
continue := false (* client is done *) continue := false (* client is done *)

View file

@ -228,7 +228,9 @@ module Request : sig
path_components: string list; path_components: string list;
query: (string*string) list; query: (string*string) list;
body: 'body; body: 'body;
start_time: float; (** @since NEXT_RELEASE *) start_time: float;
(** Obtained via [get_time_s] in {!create}
@since NEXT_RELEASE *)
} }
(** A request with method, path, host, headers, and a body, sent by a client. (** A request with method, path, host, headers, and a body, sent by a client.
@ -238,8 +240,9 @@ module Request : sig
entirely read as a string via {!read_body_full}. entirely read as a string via {!read_body_full}.
@since 0.6 The field [query] was added and contains the query parameters in ["?foo=bar,x=y"] @since 0.6 The field [query] was added and contains the query parameters in ["?foo=bar,x=y"]
@since 0.6 The field [path_components] is the part of the path that precedes [query] and is split on ["/"]. @since 0.6 The field [path_components] is the part of the path that precedes [query] and is split on ["/"].
@since NEXT_RELEASE the type is a private alias
@since NEXT_RELEASE the field [start_time] was added
*) *)
val pp : Format.formatter -> string t -> unit val pp : Format.formatter -> string t -> unit
@ -300,7 +303,7 @@ module Request : sig
(**/**) (**/**)
(* for testing purpose, do not use *) (* for testing purpose, do not use *)
module Internal_ : sig module Internal_ : sig
val parse_req_start : ?buf:Buf_.t -> byte_stream -> unit t option val parse_req_start : ?buf:Buf_.t -> get_time_s:(unit -> float) -> byte_stream -> unit t option
val parse_body : ?buf:Buf_.t -> unit t -> byte_stream -> byte_stream t val parse_body : ?buf:Buf_.t -> unit t -> byte_stream -> byte_stream t
end end
(**/**) (**/**)
@ -503,6 +506,7 @@ val create :
?max_connections:int -> ?max_connections:int ->
?timeout:float -> ?timeout:float ->
?buf_size:int -> ?buf_size:int ->
?get_time_s:(unit -> float) ->
?new_thread:((unit -> unit) -> unit) -> ?new_thread:((unit -> unit) -> unit) ->
?addr:string -> ?addr:string ->
?port:int -> ?port:int ->
@ -537,6 +541,9 @@ val create :
systemd on Linux (or launchd on macOS). If passed in, this socket will be systemd on Linux (or launchd on macOS). If passed in, this socket will be
used instead of the [addr] and [port]. If not passed in, those will be used instead of the [addr] and [port]. If not passed in, those will be
used. This parameter exists since 0.10. used. This parameter exists since 0.10.
@param get_time_s obtain the current timestamp in seconds.
This parameter exists since NEXT_RELEASE.
*) *)
val addr : t -> string val addr : t -> string