Skip to content

Commit

Permalink
feat(http2): set Content-Length header on outgoing messages
Browse files Browse the repository at this point in the history
Closes #1547
  • Loading branch information
lnicola authored and seanmonstar committed Jun 10, 2018
1 parent f20afba commit 386fc0d
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ pub fn content_length_value(len: u64) -> HeaderValue {
}
}

pub fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) {
headers
.entry(CONTENT_LENGTH)
.unwrap()
.or_insert(content_length_value(len));
}

pub fn transfer_encoding_is_chunked(headers: &HeaderMap) -> bool {
is_chunked(headers.get_all(TRANSFER_ENCODING).into_iter())
}
Expand Down
4 changes: 4 additions & 0 deletions src/proto/h2/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use tokio_io::{AsyncRead, AsyncWrite};

use body::Payload;
use ::common::{Exec, Never};
use headers;
use super::{PipeToSendStream, SendBuf};
use ::{Body, Request, Response};

Expand Down Expand Up @@ -106,6 +107,9 @@ where
let (head, body) = req.into_parts();
let mut req = ::http::Request::from_parts(head, ());
super::strip_connection_headers(req.headers_mut());
if let Some(len) = body.content_length() {
headers::set_content_length_if_missing(req.headers_mut(), len);
}
let eos = body.is_end_stream();
let (fut, body_tx) = match tx.send_request(req, eos) {
Ok(ok) => ok,
Expand Down
4 changes: 4 additions & 0 deletions src/proto/h2/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use tokio_io::{AsyncRead, AsyncWrite};

use ::body::Payload;
use ::common::Exec;
use ::headers;
use ::service::Service;
use super::{PipeToSendStream, SendBuf};

Expand Down Expand Up @@ -171,6 +172,9 @@ where
let (head, body) = res.into_parts();
let mut res = ::http::Response::from_parts(head, ());
super::strip_connection_headers(res.headers_mut());
if let Some(len) = body.content_length() {
headers::set_content_length_if_missing(res.headers_mut(), len);
}
macro_rules! reply {
($eos:expr) => ({
match self.reply.send_response(res, $eos) {
Expand Down
23 changes: 23 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,29 @@ t! {
;
}

t! {
post_outgoing_length,
client:
request:
method: "POST",
uri: "/hello",
body: "hello, world!",
;
response:
;
server:
request:
method: "POST",
uri: "/hello",
headers: {
"content-length" => "13",
},
body: "hello, world!",
;
response:
;
}

t! {
post_chunked,
client:
Expand Down
59 changes: 59 additions & 0 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,65 @@ mod response_body_lengths {
expects_con_len: false,
});
}

#[test]
fn http2_auto_response_with_known_length() {
use hyper::body::Payload;

let server = serve();
let addr_str = format!("http://{}", server.addr());
server.reply().body("Hello, World!");

hyper::rt::run(hyper::rt::lazy(move || {
let client: Client<_, hyper::Body> = Client::builder().http2_only(true).build_http();
let uri = addr_str
.parse::<hyper::Uri>()
.expect("server addr should parse");

client
.get(uri)
.and_then(|res| {
assert_eq!(res.headers().get("content-length").unwrap(), "13");
// TODO: enable this after #1546
let _ = res.body().content_length();
// assert_eq!(res.body().content_length(), Some(13));
Ok(())
})
.map(|_| ())
.map_err(|_e| ())
}));
}

#[test]
fn http2_auto_response_with_conflicting_lengths() {
use hyper::body::Payload;

let server = serve();
let addr_str = format!("http://{}", server.addr());
server
.reply()
.header("content-length", "10")
.body("Hello, World!");

hyper::rt::run(hyper::rt::lazy(move || {
let client: Client<_, hyper::Body> = Client::builder().http2_only(true).build_http();
let uri = addr_str
.parse::<hyper::Uri>()
.expect("server addr should parse");

client
.get(uri)
.and_then(|res| {
assert_eq!(res.headers().get("content-length").unwrap(), "10");
// TODO: enable or remove this after #1546
let _ = res.body().content_length();
// assert_eq!(res.body().content_length(), Some(10));
Ok(())
})
.map(|_| ())
.map_err(|_e| ())
}));
}
}

#[test]
Expand Down

0 comments on commit 386fc0d

Please sign in to comment.