From 0ba7d13ae51972c451228ccdac867dbfd8766971 Mon Sep 17 00:00:00 2001 From: Yuchen Wu Date: Thu, 22 Oct 2020 14:36:41 -0700 Subject: [PATCH] Allow responses of HEAD requests to have empty DATA frames (#490) --- src/proto/streams/stream.rs | 6 +++- tests/h2-tests/tests/client_request.rs | 44 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/proto/streams/stream.rs b/src/proto/streams/stream.rs index c2b647c93..5bbda250c 100644 --- a/src/proto/streams/stream.rs +++ b/src/proto/streams/stream.rs @@ -286,7 +286,11 @@ impl Stream { Some(val) => *rem = val, None => return Err(()), }, - ContentLength::Head => return Err(()), + ContentLength::Head => { + if len != 0 { + return Err(()); + } + } _ => {} } diff --git a/tests/h2-tests/tests/client_request.rs b/tests/h2-tests/tests/client_request.rs index 41f8f6459..35b4beacf 100644 --- a/tests/h2-tests/tests/client_request.rs +++ b/tests/h2-tests/tests/client_request.rs @@ -1171,6 +1171,50 @@ async fn malformed_response_headers_dont_unlink_stream() { join(srv, client).await; } +#[tokio::test] +async fn allow_empty_data_for_head() { + h2_support::trace_init!(); + let (io, mut srv) = mock::new(); + + let srv = async move { + let settings = srv.assert_client_handshake().await; + assert_default_settings!(settings); + srv.recv_frame( + frames::headers(1) + .request("HEAD", "https://example.com/") + .eos(), + ) + .await; + srv.send_frame( + frames::headers(1) + .response(200) + .field("content-length", 100), + ) + .await; + srv.send_frame(frames::data(1, "").eos()).await; + }; + + let h2 = async move { + let (mut client, h2) = client::Builder::new() + .handshake::<_, Bytes>(io) + .await + .unwrap(); + tokio::spawn(async { + h2.await.expect("connection failed"); + }); + let request = Request::builder() + .method(Method::HEAD) + .uri("https://example.com/") + .body(()) + .unwrap(); + let (response, _) = client.send_request(request, true).unwrap(); + let (_, mut body) = response.await.unwrap().into_parts(); + assert_eq!(body.data().await.unwrap().unwrap(), ""); + }; + + join(srv, h2).await; +} + const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0]; const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0];