From 4be4be9891652744a5f8376d09c37feca01c53c3 Mon Sep 17 00:00:00 2001 From: Sean McArthur <sean@seanmonstar.com> Date: Sun, 14 Apr 2024 08:44:05 -0400 Subject: [PATCH] fix(client): send content-length even with no body Most request methods define a payload. If hyper detects that no body has been included, it will now include a `content-length: 0` header automatically. It will not do this for methods that don't have defined payloads (GET, HEAD, and CONNECT). --- src/proto/h1/role.rs | 23 +++++++++++++++++------ tests/client.rs | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 958340775a..cad25d1ab9 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -1288,6 +1288,13 @@ impl Client { body } else { head.headers.remove(header::TRANSFER_ENCODING); + // If we know there's body coming, set a content-length. + // But only if the method normally has a body. + // GET, HEAD, and CONNECT are assumed empty. + if !is_method_assumed_empty(&head.subject.0) { + head.headers + .insert(header::CONTENT_LENGTH, HeaderValue::from_static("0")); + } return Encoder::length(0); }; @@ -1361,12 +1368,11 @@ impl Client { // So instead of sending a "chunked" body with a 0-chunk, // assume no body here. If you *must* send a body, // set the headers explicitly. - match head.subject.0 { - Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)), - _ => { - te.insert(HeaderValue::from_static("chunked")); - Some(Encoder::chunked()) - } + if is_method_assumed_empty(&head.subject.0) { + Some(Encoder::length(0)) + } else { + te.insert(HeaderValue::from_static("chunked")); + Some(Encoder::chunked()) } } else { None @@ -1468,6 +1474,11 @@ impl Client { } } +#[cfg(feature = "client")] +fn is_method_assumed_empty(method: &Method) -> bool { + matches!(method, &Method::GET | &Method::HEAD | &Method::CONNECT) +} + #[cfg(feature = "client")] fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder { // At this point, there should not be a valid Content-Length diff --git a/tests/client.rs b/tests/client.rs index 43e1f08acb..73d080f3f7 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -888,6 +888,30 @@ test! { body: None, } +test! { + name: client_post_empty_auto_length, + + server: + expected: "\ + POST /empty HTTP/1.1\r\n\ + host: {addr}\r\n\ + content-length: 0\r\n\ + \r\n\ + ", + reply: REPLY_OK, + + client: + request: { + method: POST, + url: "http://{addr}/empty", + headers: {}, + }, + response: + status: OK, + headers: {}, + body: None, +} + test! { name: client_head_ignores_body,