Skip to content

Commit aed1d13

Browse files
zuisongNutomic
authored andcommitted
fix: stop sending content-length: 0 for GET requests (seanmonstar#2207)
Closes seanmonstar#2202
1 parent 6be8fe3 commit aed1d13

File tree

3 files changed

+74
-9
lines changed

3 files changed

+74
-9
lines changed

src/async_impl/body.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,17 @@ impl HttpBody for Body {
267267

268268
fn size_hint(&self) -> http_body::SizeHint {
269269
match self.inner {
270-
Inner::Reusable(ref bytes) => {
271-
let mut hint = http_body::SizeHint::default();
272-
hint.set_exact(bytes.len() as u64);
273-
hint
274-
}
270+
Inner::Reusable(ref bytes) => http_body::SizeHint::with_exact(bytes.len() as u64),
275271
Inner::Streaming(ref body) => body.size_hint(),
276272
}
277273
}
274+
275+
fn is_end_stream(&self) -> bool {
276+
match self.inner {
277+
Inner::Reusable(ref bytes) => bytes.is_empty(),
278+
Inner::Streaming(ref body) => body.is_end_stream(),
279+
}
280+
}
278281
}
279282

280283
// ===== impl TotalTimeoutBody =====
@@ -352,6 +355,8 @@ where
352355

353356
#[cfg(test)]
354357
mod tests {
358+
use http_body::Body as _;
359+
355360
use super::Body;
356361

357362
#[test]
@@ -360,4 +365,19 @@ mod tests {
360365
let body = Body::from(&test_data[..]);
361366
assert_eq!(body.as_bytes(), Some(&test_data[..]));
362367
}
368+
369+
#[test]
370+
fn body_exact_length() {
371+
let empty_body = Body::empty();
372+
assert!(empty_body.is_end_stream());
373+
assert_eq!(empty_body.size_hint().exact(), Some(0));
374+
375+
let bytes_body = Body::reusable("abc".into());
376+
assert!(!bytes_body.is_end_stream());
377+
assert_eq!(bytes_body.size_hint().exact(), Some(3));
378+
379+
let stream_body = Body::streaming(bytes_body);
380+
assert!(!stream_body.is_end_stream());
381+
assert_eq!(stream_body.size_hint().exact(), None);
382+
}
363383
}

tests/blocking.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
mod support;
22

3-
#[cfg(feature = "json")]
4-
use http::header::CONTENT_TYPE;
3+
use http::header::{CONTENT_LENGTH, CONTENT_TYPE, TRANSFER_ENCODING};
54
use http_body_util::BodyExt;
65
#[cfg(feature = "json")]
76
use std::collections::HashMap;
@@ -21,6 +20,29 @@ fn test_response_text() {
2120
assert_eq!(b"Hello", body.as_bytes());
2221
}
2322

23+
#[test]
24+
fn donot_set_conent_length_0_if_have_no_body() {
25+
let server = server::http(move |req| async move {
26+
let headers = req.headers();
27+
assert_eq!(headers.get(CONTENT_LENGTH), None);
28+
assert!(headers.get(CONTENT_TYPE).is_none());
29+
assert!(headers.get(TRANSFER_ENCODING).is_none());
30+
dbg!(&headers);
31+
http::Response::default()
32+
});
33+
34+
let url = format!("http://{}/conent-length", server.addr());
35+
let res = reqwest::blocking::Client::builder()
36+
.no_proxy()
37+
.build()
38+
.expect("client builder")
39+
.post(&url)
40+
.send()
41+
.expect("request");
42+
43+
assert_eq!(res.status(), reqwest::StatusCode::OK);
44+
}
45+
2446
#[test]
2547
#[cfg(feature = "charset")]
2648
fn test_response_non_utf_8_text() {

tests/client.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ mod support;
33

44
use support::server;
55

6-
#[cfg(feature = "json")]
7-
use http::header::CONTENT_TYPE;
6+
use http::header::{CONTENT_LENGTH, CONTENT_TYPE, TRANSFER_ENCODING};
87
#[cfg(feature = "json")]
98
use std::collections::HashMap;
109

@@ -54,6 +53,30 @@ async fn auto_headers() {
5453
assert_eq!(res.remote_addr(), Some(server.addr()));
5554
}
5655

56+
#[tokio::test]
57+
async fn donot_set_conent_length_0_if_have_no_body() {
58+
let server = server::http(move |req| async move {
59+
let headers = req.headers();
60+
assert_eq!(headers.get(CONTENT_LENGTH), None);
61+
assert!(headers.get(CONTENT_TYPE).is_none());
62+
assert!(headers.get(TRANSFER_ENCODING).is_none());
63+
dbg!(&headers);
64+
http::Response::default()
65+
});
66+
67+
let url = format!("http://{}/conent-length", server.addr());
68+
let res = reqwest::Client::builder()
69+
.no_proxy()
70+
.build()
71+
.expect("client builder")
72+
.get(&url)
73+
.send()
74+
.await
75+
.expect("request");
76+
77+
assert_eq!(res.status(), reqwest::StatusCode::OK);
78+
}
79+
5780
#[tokio::test]
5881
async fn user_agent() {
5982
let server = server::http(move |req| async move {

0 commit comments

Comments
 (0)