fix(http2): received Body::size_hint() now return 0 if implicitly empty (#2715)

An HTTP/2 stream may include a set of headers, and a flag signalling
END-STREAM, even if a `content-length` isn't included. hyper wouldn't
notice, and so the `Body` would report a size-hint of `0..MAX`. hyper
now notices that the stream is ended, and couldn't possibly include any
bytes for the body, and thus will give a size-hint of `0` exactly.
This commit is contained in:
Sean McArthur
2021-12-06 14:14:41 -08:00
committed by GitHub
parent ce8242571f
commit 84b78b6c87
4 changed files with 41 additions and 5 deletions

View File

@@ -204,9 +204,14 @@ impl Body {
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
pub(crate) fn h2(
recv: h2::RecvStream,
content_length: DecodedLength,
mut content_length: DecodedLength,
ping: ping::Recorder,
) -> Self {
// If the stream is already EOS, then the "unknown length" is clearly
// actually ZERO.
if !content_length.is_exact() && recv.is_end_stream() {
content_length = DecodedLength::ZERO;
}
let body = Body::new(Kind::H2 {
ping,
content_length,

View File

@@ -68,6 +68,16 @@ impl DecodedLength {
}
}
}
/// Returns whether this represents an exact length.
///
/// This includes 0, which of course is an exact known length.
///
/// It would return false if "chunked" or otherwise size-unknown.
#[cfg(feature = "http2")]
pub(crate) fn is_exact(&self) -> bool {
self.0 <= MAX_LEN
}
}
impl fmt::Debug for DecodedLength {

View File

@@ -484,12 +484,13 @@ where
}
}
// automatically set Content-Length from body...
if let Some(len) = body.size_hint().exact() {
headers::set_content_length_if_missing(res.headers_mut(), len);
}
if !body.is_end_stream() {
// automatically set Content-Length from body...
if let Some(len) = body.size_hint().exact() {
headers::set_content_length_if_missing(res.headers_mut(), len);
}
let body_tx = reply!(me, res, false);
H2StreamState::Body {
pipe: PipeToSendStream::new(body, body_tx),