From bfc6010da5c3e01a80076be1a0bbef1ffdbd61cd Mon Sep 17 00:00:00 2001 From: Antonio Nuno Monteiro Date: Tue, 8 Dec 2020 19:02:05 -0800 Subject: [PATCH] Add a test for non-zero content-length header in a 304 response (#88) similar to what we tested for in #87 --- lib/response.ml | 10 +++++++++- lib_test/test_client_connection.ml | 26 ++++++++++++++++++++++++++ nix/sources.nix | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/response.ml b/lib/response.ml index c91701a1..89ff333f 100644 --- a/lib/response.ml +++ b/lib/response.ml @@ -56,7 +56,15 @@ let proxy_error = `Error `Bad_gateway let server_error = `Error `Internal_server_error let body_length ?(proxy=false) ~request_method { status; headers; _ } = match status, request_method with - | (`No_content | `Not_modified), _ -> `Fixed 0L + | (`No_content | `Not_modified), _ -> + (* From RFC7230§3.3.2: + A server MAY send a Content-Length header field in a 304 (Not + Modified) response to a conditional GET request (Section 4.1 of + [RFC7232]); a server MUST NOT send Content-Length in such a response + unless its field-value equals the decimal number of octets that would + have been sent in the payload body of a 200 (OK) response to the same + request. *) + `Fixed 0L | _, `HEAD -> (* From RFC7230§3.3.2: A server MAY send a Content-Length header field in a response to a diff --git a/lib_test/test_client_connection.ml b/lib_test/test_client_connection.ml index d9ee8a3e..cb624e51 100644 --- a/lib_test/test_client_connection.ml +++ b/lib_test/test_client_connection.ml @@ -1377,6 +1377,31 @@ let test_chunked_error () = connection_is_shutdown t; ;; +let test_304_not_modified () = + let error_handler_called = ref false in + let request' = Request.create `GET "/" in + let response = Response.create + ~headers:(Headers.of_list ["content-length", "5"]) + `Not_modified + in + + let t = create ?config:None in + let body = + request + t + request' + ~response_handler:(default_response_handler response) + ~error_handler:(fun _ -> error_handler_called := true) + in + Body.close_writer body; + write_request t request'; + read_response t response; + let c = read_eof t Bigstringaf.empty ~off:0 ~len:0 in + Alcotest.(check int) "read_eof with no input returns 0" 0 c; + connection_is_shutdown t; + Alcotest.(check bool) "error handler not called" false !error_handler_called; +;; + let tests = [ "commit parse after every header line", `Quick, test_commit_parse_after_every_header ; "GET" , `Quick, test_get @@ -1412,4 +1437,5 @@ let tests = ; "reader EOF race condition causes state machine to issue writer yield", `Quick, test_race_condition_writer_issues_yield_after_reader_eof ; "multiple responses in single read", `Quick, test_multiple_responses_in_single_read ; "test chunked error", `Quick, test_chunked_error + ; "304 Not Modified with Content-Length", `Quick, test_304_not_modified ] diff --git a/nix/sources.nix b/nix/sources.nix index fb61813f..a7a6b1cd 100644 --- a/nix/sources.nix +++ b/nix/sources.nix @@ -3,7 +3,7 @@ let overlays = builtins.fetchTarball - https://github.com/anmonteiro/nix-overlays/archive/ce6fc101.tar.gz; + https://github.com/anmonteiro/nix-overlays/archive/7fc23e0.tar.gz; in