From c6b92cbca902a62850b72269384fcbc32d30cb96 Mon Sep 17 00:00:00 2001 From: Ruben2424 <61056653+Ruben2424@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:26:43 +0200 Subject: [PATCH] Closing the Request stream for sending is handled by the client at the moment. Add exception to the compliance check and improve documentation. (#260) --- .../specs/rfc9114/exception/4.1.toml | 23 +++++++++++++++++++ ci/compliance/specs/rfc9114/todo/4.1.toml | 12 ---------- h3/src/client/stream.rs | 20 +++++++--------- h3/src/server/stream.rs | 9 +++----- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/ci/compliance/specs/rfc9114/exception/4.1.toml b/ci/compliance/specs/rfc9114/exception/4.1.toml index 6aa9122d..8a0bd6e0 100644 --- a/ci/compliance/specs/rfc9114/exception/4.1.toml +++ b/ci/compliance/specs/rfc9114/exception/4.1.toml @@ -45,3 +45,26 @@ the request and close the stream normally. reason = ''' h3 does not need to do anything specific. ''' + + +[[exception]] +target = "https://www.rfc-editor.org/rfc/rfc9114#section-4.1" +quote = ''' +After sending a final +response, the server MUST close the stream for sending. +''' +reason = ''' +Users of h3 should close the stream for sending after sending a final response. As documented in the server docs. +''' + +[[exception]] +target = "https://www.rfc-editor.org/rfc/rfc9114#section-4.1" +quote = ''' +After sending a request, a client MUST +close the stream for sending. +''' +reason = ''' +Users of h3 should close the stream for sending after sending a request. As documented in the client docs. +''' + + diff --git a/ci/compliance/specs/rfc9114/todo/4.1.toml b/ci/compliance/specs/rfc9114/todo/4.1.toml index 78539bc0..cac141dd 100644 --- a/ci/compliance/specs/rfc9114/todo/4.1.toml +++ b/ci/compliance/specs/rfc9114/todo/4.1.toml @@ -40,21 +40,9 @@ more interim responses (1xx; see Section 15.2 of [HTTP]) precede a final response to the same request. ''' -[[TODO]] -quote = ''' -After sending a request, a client MUST -close the stream for sending. -''' - [[TODO]] quote = ''' Unless using the CONNECT method (see Section 4.4), clients MUST NOT make stream closure dependent on receiving a response to their request. ''' - -[[TODO]] -quote = ''' -After sending a final -response, the server MUST close the stream for sending. -''' diff --git a/h3/src/client/stream.rs b/h3/src/client/stream.rs index b94e40d4..ba284fb7 100644 --- a/h3/src/client/stream.rs +++ b/h3/src/client/stream.rs @@ -15,19 +15,19 @@ use std::convert::TryFrom; /// Manage request bodies transfer, response and trailers. /// -/// Once a request has been sent via [`send_request()`], a response can be awaited by calling -/// [`recv_response()`]. A body for this request can be sent with [`send_data()`], then the request -/// shall be completed by either sending trailers with [`send_trailers()`], or [`finish()`]. +/// Once a request has been sent via [`crate::client::SendRequest::send_request()`], a response can be awaited by calling +/// [`RequestStream::recv_response()`]. A body for this request can be sent with [`RequestStream::send_data()`], then the request +/// shall be completed by either sending trailers with [`RequestStream::finish()`]. /// -/// After receiving the response's headers, it's body can be read by [`recv_data()`] until it returns -/// `None`. Then the trailers will eventually be available via [`recv_trailers()`]. +/// After receiving the response's headers, it's body can be read by [`RequestStream::recv_data()`] until it returns +/// `None`. Then the trailers will eventually be available via [`RequestStream::recv_trailers()`]. /// /// TODO: If data is polled before the response has been received, an error will be thrown. /// /// TODO: If trailers are polled but the body hasn't been fully received, an UNEXPECT_FRAME error will be /// thrown /// -/// Whenever the client wants to cancel this request, it can call [`stop_sending()`], which will +/// Whenever the client wants to cancel this request, it can call [`RequestStream::stop_sending()`], which will /// put an end to any transfer concerning it. /// /// # Examples @@ -183,9 +183,7 @@ where /// Send a set of trailers to end the request. /// - /// Either [`RequestStream::finish`] or - /// [`RequestStream::send_trailers`] must be called to finalize a - /// request. + /// [`RequestStream::finish()`] must be called to finalize a request. #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] pub async fn send_trailers(&mut self, trailers: HeaderMap) -> Result<(), Error> { self.inner.send_trailers(trailers).await @@ -193,9 +191,7 @@ where /// End the request without trailers. /// - /// Either [`RequestStream::finish`] or - /// [`RequestStream::send_trailers`] must be called to finalize a - /// request. + /// [`RequestStream::finish()`] must be called to finalize a request. #[cfg_attr(feature = "tracing", instrument(skip_all, level = "trace"))] pub async fn finish(&mut self) -> Result<(), Error> { self.inner.finish().await diff --git a/h3/src/server/stream.rs b/h3/src/server/stream.rs index 975537ed..abc3b299 100644 --- a/h3/src/server/stream.rs +++ b/h3/src/server/stream.rs @@ -40,6 +40,7 @@ use tracing::{error, instrument}; /// /// The [`RequestStream`] struct is used to send and/or receive /// information from the client. +/// After sending the final response, call [`RequestStream::finish`] to close the stream. pub struct RequestStream { pub(super) inner: crate::connection::RequestStream, pub(super) request_end: Arc, @@ -151,18 +152,14 @@ where /// Send a set of trailers to end the response. /// - /// Either [`RequestStream::finish`] or - /// [`RequestStream::send_trailers`] must be called to finalize a - /// request. + /// [`RequestStream::finish`] must be called to finalize a request. pub async fn send_trailers(&mut self, trailers: HeaderMap) -> Result<(), Error> { self.inner.send_trailers(trailers).await } /// End the response without trailers. /// - /// Either [`RequestStream::finish`] or - /// [`RequestStream::send_trailers`] must be called to finalize a - /// request. + /// [`RequestStream::finish`] must be called to finalize a request. pub async fn finish(&mut self) -> Result<(), Error> { self.inner.finish().await }