Skip to content

Commit

Permalink
extra bytes in HTTP response after fully decompressed body are an error
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrey36652 committed Nov 30, 2024
1 parent c9faaeb commit 925f147
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/async_impl/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ impl HttpBody for Decoder {
let stream_reader = gzip_decoder.get_mut();
let peekable_io_stream = stream_reader.get_mut();
match futures_core::ready!(Pin::new(peekable_io_stream).poll_next(cx)) {
Some(Ok(bytes)) => Poll::Ready(Some(Ok(Frame::data(bytes)))),
Some(Ok(bytes)) => Poll::Ready(Some(Err(crate::error::decode("there are extra bytes after body has been decompressed")))),
Some(Err(err)) => Poll::Ready(Some(Err(crate::error::decode_io(err)))),
None => Poll::Ready(None),
}
Expand Down
61 changes: 61 additions & 0 deletions tests/gzip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,64 @@ async fn test_chunked_fragmented_response_2() {
);
assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);
}

#[tokio::test]
async fn test_chunked_fragmented_response_with_extra_bytes() {
const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =
tokio::time::Duration::from_millis(1000);
const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);

let server = server::low_level_with_response(|_raw_request, client_socket| {
Box::new(async move {
let response_first_part = b"HTTP/1.1 200 OK\x0d\x0a\
Content-Type: text/plain\x0d\x0a\
Transfer-Encoding: chunked\x0d\x0a\
Connection: keep-alive\x0d\x0a\
Content-Encoding: gzip\x0d\x0a\
\x0d\x0a\
55\x0d\x0a\
\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xabV*\xae\xccM\xca\xcfQ\xb2Rr\x0aq\x0e\x0dv\x09Q\xd2Q\xca/H\xcd\xf3\xcc+I-J-.\x01J\x98\x1b\x18\x98\x9a\xe9\x99\x9a\x18\x03\xa5J2sS\x95\xac\x0c\xcd\x8d\x8cM\x8cLML\x0c---j\x01\xd7Gb;D\x00\x00\x00";
let response_second_part = b"\x0d\x0a2ab\x0d\x0a0\x0d\x0a\x0d\x0a";

client_socket
.write_all(response_first_part)
.await
.expect("response_first_part write_all failed");
client_socket
.flush()
.await
.expect("response_first_part flush failed");

tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;

client_socket
.write_all(response_second_part)
.await
.expect("response_second_part write_all failed");
client_socket
.flush()
.await
.expect("response_second_part flush failed");
})
});

let start = tokio::time::Instant::now();

let client = reqwest::Client::builder()
.connection_verbose(true)
.timeout(Duration::from_secs(15))
.pool_idle_timeout(Some(std::time::Duration::from_secs(300)))
.pool_max_idle_per_host(5)
.build()
.expect("reqwest client init error");

let res = client
.get(&format!("http://{}/", server.addr()))
.send()
.await
.expect("response");

let err = res.text().await.expect_err("there must be an error");
assert!(err.is_decode());
assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);
}

0 comments on commit 925f147

Please sign in to comment.