Skip to content

Commit

Permalink
Fix content length for HEAD requests
Browse files Browse the repository at this point in the history
According to RFCs, HEAD requests do not have any content, but may include
content length to inform the client about the size of the resource.

closes inhabitedtype#87
  • Loading branch information
Lupus authored and anmonteiro committed Dec 9, 2020
1 parent 909297d commit fad584a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/response.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ 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
| _, `HEAD ->
(* From RFC7230§3.3.2:
A server MAY send a Content-Length header field in a response to a
HEAD request (Section 4.3.2 of [RFC7231]); 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 response if the same request had used the GET method. *)
`Fixed 0L
| s, _ when Status.is_informational s -> `Fixed 0L
| s, `CONNECT when Status.is_successful s -> `Close_delimited
| _, _ ->
Expand Down
26 changes: 26 additions & 0 deletions lib_test/test_client_connection.ml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,31 @@ let test_get () =
read_string t "d\r\nHello, world!\r\n0\r\n\r\n";
;;

let test_head () =
let error_handler_called = ref false in
let request' = Request.create `HEAD "/" in
let response = Response.create
~headers:(Headers.of_list ["content-length", "5"])
`OK
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 test_get_last_close () =
(* Multiple GET requests, the last one closes the connection *)
let request' = Request.create `GET "/" in
Expand Down Expand Up @@ -1355,6 +1380,7 @@ let test_chunked_error () =
let tests =
[ "commit parse after every header line", `Quick, test_commit_parse_after_every_header
; "GET" , `Quick, test_get
; "HEAD" , `Quick, test_head
; "Response EOF", `Quick, test_response_eof
; "Response header order preserved", `Quick, test_response_header_order
; "report_exn" , `Quick, test_report_exn
Expand Down

0 comments on commit fad584a

Please sign in to comment.