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>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
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;
|
||||
@@ -10,6 +8,8 @@ use bytes::BytesMut;
|
||||
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;
|
||||
@@ -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>,
|
||||
@@ -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",
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user