Skip to content

Commit 67b7313

Browse files
jannesJannes Timm
and
Jannes Timm
authored
fix(server): don't add implicit content-length to HEAD responses (#2836)
HEAD responses should not have content-length implicitly set by hyper. Co-authored-by: Jannes Timm <jannes@cloudflare.com>
1 parent faf24c6 commit 67b7313

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

src/proto/h1/role.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use std::fmt::{self, Write};
22
use std::mem::MaybeUninit;
33

4-
#[cfg(all(feature = "server", feature = "runtime"))]
5-
use tokio::time::Instant;
64
#[cfg(any(test, feature = "server", feature = "ffi"))]
75
use bytes::Bytes;
86
use bytes::BytesMut;
97
#[cfg(feature = "server")]
108
use http::header::ValueIter;
119
use http::header::{self, Entry, HeaderName, HeaderValue};
1210
use http::{HeaderMap, Method, StatusCode, Version};
11+
#[cfg(all(feature = "server", feature = "runtime"))]
12+
use tokio::time::Instant;
1313
use tracing::{debug, error, trace, trace_span, warn};
1414

1515
use crate::body::DecodedLength;
@@ -487,6 +487,10 @@ impl Server {
487487
}
488488
}
489489

490+
fn can_have_implicit_zero_content_length(method: &Option<Method>, status: StatusCode) -> bool {
491+
Server::can_have_content_length(method, status) && method != &Some(Method::HEAD)
492+
}
493+
490494
fn encode_headers_with_lower_case(
491495
msg: Encode<'_, StatusCode>,
492496
dst: &mut Vec<u8>,
@@ -839,7 +843,10 @@ impl Server {
839843
}
840844
}
841845
None | Some(BodyLength::Known(0)) => {
842-
if Server::can_have_content_length(msg.req_method, msg.head.subject) {
846+
if Server::can_have_implicit_zero_content_length(
847+
msg.req_method,
848+
msg.head.subject,
849+
) {
843850
header_name_writer.write_full_header_line(
844851
dst,
845852
"content-length: 0\r\n",
@@ -1033,7 +1040,7 @@ impl Http1Transaction for Client {
10331040
}
10341041

10351042
#[cfg(feature = "ffi")]
1036-
if let Some(ref mut header_order) = header_order {
1043+
if let Some(ref mut header_order) = header_order {
10371044
header_order.append(&name);
10381045
}
10391046

tests/server.rs

+20
Original file line numberDiff line numberDiff line change
@@ -2421,6 +2421,26 @@ fn skips_content_length_and_body_for_304_responses() {
24212421
assert_eq!(lines.next(), None);
24222422
}
24232423

2424+
#[test]
2425+
fn no_implicit_zero_content_length_for_head_responses() {
2426+
let server = serve();
2427+
server.reply().status(hyper::StatusCode::OK).body([]);
2428+
let mut req = connect(server.addr());
2429+
req.write_all(
2430+
b"\
2431+
HEAD / HTTP/1.1\r\n\
2432+
Host: example.domain\r\n\
2433+
Connection: close\r\n\
2434+
\r\n\
2435+
",
2436+
)
2437+
.unwrap();
2438+
2439+
let mut response = String::new();
2440+
req.read_to_string(&mut response).unwrap();
2441+
assert!(!response.contains("content-length:"));
2442+
}
2443+
24242444
#[tokio::test]
24252445
async fn http2_keep_alive_detects_unresponsive_client() {
24262446
let _ = pretty_env_logger::try_init();

0 commit comments

Comments
 (0)