Skip to content

Commit

Permalink
fix(server): don't add implicit content-length to HEAD responses (#2836)
Browse files Browse the repository at this point in the history
HEAD responses should not have content-length implicitly set by hyper.

Co-authored-by: Jannes Timm <[email protected]>
  • Loading branch information
jannes and Jannes Timm authored May 18, 2022
1 parent faf24c6 commit 67b7313
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
15 changes: 11 additions & 4 deletions src/proto/h1/role.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::fmt::{self, Write};
use std::mem::MaybeUninit;

#[cfg(all(feature = "server", feature = "runtime"))]
use tokio::time::Instant;
#[cfg(any(test, feature = "server", feature = "ffi"))]
use bytes::Bytes;
use bytes::BytesMut;
#[cfg(feature = "server")]
use http::header::ValueIter;
use http::header::{self, Entry, HeaderName, HeaderValue};
use http::{HeaderMap, Method, StatusCode, Version};
#[cfg(all(feature = "server", feature = "runtime"))]
use tokio::time::Instant;
use tracing::{debug, error, trace, trace_span, warn};

use crate::body::DecodedLength;
Expand Down Expand Up @@ -487,6 +487,10 @@ impl Server {
}
}

fn can_have_implicit_zero_content_length(method: &Option<Method>, status: StatusCode) -> bool {
Server::can_have_content_length(method, status) && method != &Some(Method::HEAD)
}

fn encode_headers_with_lower_case(
msg: Encode<'_, StatusCode>,
dst: &mut Vec<u8>,
Expand Down Expand Up @@ -839,7 +843,10 @@ impl Server {
}
}
None | Some(BodyLength::Known(0)) => {
if Server::can_have_content_length(msg.req_method, msg.head.subject) {
if Server::can_have_implicit_zero_content_length(
msg.req_method,
msg.head.subject,
) {
header_name_writer.write_full_header_line(
dst,
"content-length: 0\r\n",
Expand Down Expand Up @@ -1033,7 +1040,7 @@ impl Http1Transaction for Client {
}

#[cfg(feature = "ffi")]
if let Some(ref mut header_order) = header_order {
if let Some(ref mut header_order) = header_order {
header_order.append(&name);
}

Expand Down
20 changes: 20 additions & 0 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2421,6 +2421,26 @@ fn skips_content_length_and_body_for_304_responses() {
assert_eq!(lines.next(), None);
}

#[test]
fn no_implicit_zero_content_length_for_head_responses() {
let server = serve();
server.reply().status(hyper::StatusCode::OK).body([]);
let mut req = connect(server.addr());
req.write_all(
b"\
HEAD / HTTP/1.1\r\n\
Host: example.domain\r\n\
Connection: close\r\n\
\r\n\
",
)
.unwrap();

let mut response = String::new();
req.read_to_string(&mut response).unwrap();
assert!(!response.contains("content-length:"));
}

#[tokio::test]
async fn http2_keep_alive_detects_unresponsive_client() {
let _ = pretty_env_logger::try_init();
Expand Down

0 comments on commit 67b7313

Please sign in to comment.