From c38c94cb16cc8076231f015b15d29c8b9287153b Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Oct 2021 12:40:27 +0200 Subject: [PATCH] Make :status in requests be a stream error --- src/frame/headers.rs | 5 +++++ src/server.rs | 4 +--- tests/h2-support/src/frames.rs | 10 +++++++++- tests/h2-tests/tests/server.rs | 24 ++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/frame/headers.rs b/src/frame/headers.rs index cfc6a1a..0851d76 100644 --- a/src/frame/headers.rs +++ b/src/frame/headers.rs @@ -575,6 +575,11 @@ impl Pseudo { } } + #[cfg(feature = "unstable")] + pub fn set_status(&mut self, value: StatusCode) { + self.status = Some(value); + } + pub fn set_scheme(&mut self, scheme: uri::Scheme) { let bytes_str = match scheme.as_str() { "http" => BytesStr::from_static("http"), diff --git a/src/server.rs b/src/server.rs index 6662712..e14cdb0 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1410,10 +1410,8 @@ impl proto::Peer for Peer { malformed!("malformed headers: missing method"); } - // Specifying :status for a request is a protocol error if pseudo.status.is_some() { - tracing::trace!("malformed headers: :status field on request; PROTOCOL_ERROR"); - return Err(Error::library_go_away(Reason::PROTOCOL_ERROR)); + malformed!("malformed headers: :status field on request"); } // Convert the URI diff --git a/tests/h2-support/src/frames.rs b/tests/h2-support/src/frames.rs index 05fb320..824bc5c 100644 --- a/tests/h2-support/src/frames.rs +++ b/tests/h2-support/src/frames.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; use std::fmt; use bytes::Bytes; -use http::{self, HeaderMap}; +use http::{self, HeaderMap, StatusCode}; use h2::frame::{self, Frame, StreamId}; @@ -162,6 +162,14 @@ impl Mock { Mock(frame) } + pub fn status(self, value: StatusCode) -> Self { + let (id, mut pseudo, fields) = self.into_parts(); + + pseudo.set_status(value); + + Mock(frame::Headers::new(id, pseudo, fields)) + } + pub fn scheme(self, value: &str) -> Self { let (id, mut pseudo, fields) = self.into_parts(); let value = value.parse().unwrap(); diff --git a/tests/h2-tests/tests/server.rs b/tests/h2-tests/tests/server.rs index 770750d..ab47dfe 100644 --- a/tests/h2-tests/tests/server.rs +++ b/tests/h2-tests/tests/server.rs @@ -1025,6 +1025,30 @@ async fn server_error_on_unclean_shutdown() { srv.await.expect_err("should error"); } +#[tokio::test] +async fn server_error_on_status_in_request() { + h2_support::trace_init!(); + + let (io, mut client) = mock::new(); + + let client = async move { + let settings = client.assert_server_handshake().await; + assert_default_settings!(settings); + client + .send_frame(frames::headers(1).status(StatusCode::OK)) + .await; + client.recv_frame(frames::reset(1).protocol_error()).await; + }; + + let srv = async move { + let mut srv = server::handshake(io).await.expect("handshake"); + + assert!(srv.next().await.is_none()); + }; + + join(client, srv).await; +} + #[tokio::test] async fn request_without_authority() { h2_support::trace_init!();