diff --git a/lib/parse.ml b/lib/parse.ml index 774cec3..be1ff53 100644 --- a/lib/parse.ml +++ b/lib/parse.ml @@ -103,6 +103,7 @@ let header = lift2 (fun key value -> (key, value)) (take_till P.is_space_or_colon <* char ':' <* spaces) (take_till P.is_cr <* eol >>| String.trim) + <* commit "header" let headers = diff --git a/lib_test/test_httpaf.ml b/lib_test/test_httpaf.ml index aee54f6..254cad9 100644 --- a/lib_test/test_httpaf.ml +++ b/lib_test/test_httpaf.ml @@ -449,6 +449,30 @@ module Server_connection = struct connection_is_shutdown t; ;; + let test_commit_parse_after_every_header () = + let t = create default_request_handler in + let request_line = "GET / HTTP/1.1\r\n" in + let single_header = "Links: /path/to/some/website\r\n" in + let r = + (* Each header is 30 bytes *) + request_line ^ single_header ^ single_header ^ "connection: close\r\n\r\n" + in + let bs = Bigstringaf.of_string r ~off:0 ~len:(String.length r) in + let c = read t bs ~off:0 ~len:30 in + Alcotest.(check int) "only reads the request line" (String.length request_line) c; + + let c' = + read t bs ~off:c ~len:(String.length single_header) + in + Alcotest.(check int) "parser can read a single header and commit" (String.length single_header) c'; + + let c'' = read_eof t bs ~off:(c + c') ~len:(String.length r - (c + c')) in + Alcotest.(check int) "read_eof with the rest of the input is accepted" (String.length r - (c + c')) c''; + + write_response t (Response.create `OK); + connection_is_shutdown t; + ;; + let test_single_get () = (* Single GET *) let t = create default_request_handler in @@ -1004,6 +1028,7 @@ Accept-Language: en-US,en;q=0.5\r\n\r\n"; let tests = [ "initial reader state" , `Quick, test_initial_reader_state ; "shutdown reader closed", `Quick, test_reader_is_closed_after_eof + ; "commit parse after every header line", `Quick, test_commit_parse_after_every_header ; "single GET" , `Quick, test_single_get ; "multiple GETs" , `Quick, test_multiple_get ; "asynchronous response" , `Quick, test_asynchronous_response @@ -1107,6 +1132,50 @@ module Client_connection = struct let no_error_handler _ = assert false + let test_commit_parse_after_every_header () = + let request' = Request.create `GET "/" in + let response = + Response.create + ~headers:(Headers.of_list + [ "Links", "/path/to/some/website" + ; "Links", "/path/to/some/website" + ; "connection", "close" + ]) + `OK + in + + let t = create ?config:None in + let body = + request + t + request' + ~response_handler:(default_response_handler response) + ~error_handler:no_error_handler + in + Body.close_writer body; + write_request t request'; + + let response_line = "HTTP/1.1 200 OK\r\n" in + let single_header = "Links: /path/to/some/website\r\n" in + let r = + (* Each header is 30 bytes *) + response_line ^ single_header ^ single_header ^ "connection: close\r\n\r\n" + in + let bs = Bigstringaf.of_string r ~off:0 ~len:(String.length r) in + let c = read t bs ~off:0 ~len:(String.length response_line + 15) in + Alcotest.(check int) "only reads the response line" (String.length response_line) c; + + let c' = + read t bs ~off:c ~len:(String.length single_header) + in + Alcotest.(check int) "parser can read a single header and commit" (String.length single_header) c'; + + let c'' = read_eof t bs ~off:(c + c') ~len:(String.length r - (c + c')) in + Alcotest.(check int) "read_eof with the rest of the input is accepted" (String.length r - (c + c')) c''; + + connection_is_shutdown t; + ;; + let test_get () = let request' = Request.create `GET "/" in let response = Response.create `OK in @@ -1583,7 +1652,8 @@ module Client_connection = struct ;; let tests = - [ "GET" , `Quick, test_get + [ "commit parse after every header line", `Quick, test_commit_parse_after_every_header + ; "GET" , `Quick, test_get ; "Response EOF", `Quick, test_response_eof ; "report_exn" , `Quick, test_report_exn ; "input_shrunk", `Quick, test_input_shrunk diff --git a/nix/sources.nix b/nix/sources.nix index 2a5b4b7..624bd28 100644 --- a/nix/sources.nix +++ b/nix/sources.nix @@ -2,8 +2,8 @@ let overlays = builtins.fetchTarball { - url = https://github.com/anmonteiro/nix-overlays/archive/efe73147.tar.gz; - sha256 = "0ny0dgm018i9x9xwr5356fkyqmy3jr325ypjsg35nx0jg597g7y6"; + url = https://github.com/anmonteiro/nix-overlays/archive/fae33982.tar.gz; + sha256 = "0f1akg612xy8a1bjyk9s2bi8db5w77qbz7xgcpfijzxz20bfh816"; }; in