Skip to content

Commit 172fdfa

Browse files
committedApr 15, 2024·
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).
1 parent b79be91 commit 172fdfa

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed
 

‎src/proto/h1/role.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,13 @@ impl Client {
12881288
body
12891289
} else {
12901290
head.headers.remove(header::TRANSFER_ENCODING);
1291+
// If we know there's body coming, set a content-length.
1292+
// But only if the method normally has a body.
1293+
// GET, HEAD, and CONNECT are assumed empty.
1294+
if !is_method_assumed_empty(&head.subject.0) {
1295+
head.headers
1296+
.insert(header::CONTENT_LENGTH, HeaderValue::from_static("0"));
1297+
}
12911298
return Encoder::length(0);
12921299
};
12931300

@@ -1361,12 +1368,11 @@ impl Client {
13611368
// So instead of sending a "chunked" body with a 0-chunk,
13621369
// assume no body here. If you *must* send a body,
13631370
// set the headers explicitly.
1364-
match head.subject.0 {
1365-
Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)),
1366-
_ => {
1367-
te.insert(HeaderValue::from_static("chunked"));
1368-
Some(Encoder::chunked())
1369-
}
1371+
if is_method_assumed_empty(&head.subject.0) {
1372+
Some(Encoder::length(0))
1373+
} else {
1374+
te.insert(HeaderValue::from_static("chunked"));
1375+
Some(Encoder::chunked())
13701376
}
13711377
} else {
13721378
None
@@ -1468,6 +1474,11 @@ impl Client {
14681474
}
14691475
}
14701476

1477+
#[cfg(feature = "client")]
1478+
fn is_method_assumed_empty(method: &Method) -> bool {
1479+
matches!(method, &Method::GET | &Method::HEAD | &Method::CONNECT)
1480+
}
1481+
14711482
#[cfg(feature = "client")]
14721483
fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder {
14731484
// At this point, there should not be a valid Content-Length

‎tests/client.rs

+24
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,30 @@ test! {
888888
body: None,
889889
}
890890

891+
test! {
892+
name: client_post_empty_auto_length,
893+
894+
server:
895+
expected: "\
896+
POST /empty HTTP/1.1\r\n\
897+
host: {addr}\r\n\
898+
content-length: 0\r\n\
899+
\r\n\
900+
",
901+
reply: REPLY_OK,
902+
903+
client:
904+
request: {
905+
method: POST,
906+
url: "http://{addr}/empty",
907+
headers: {},
908+
},
909+
response:
910+
status: OK,
911+
headers: {},
912+
body: None,
913+
}
914+
891915
test! {
892916
name: client_head_ignores_body,
893917

1 commit comments

Comments
 (1)

bagder commented on Apr 16, 2024

@bagder
Contributor

This new surprise header breaks curl test cases: curl/curl#13380

Please sign in to comment.