diff --git a/Cargo.toml b/Cargo.toml index 8941140742..84d5594b16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -253,3 +253,6 @@ required-features = ["full"] name = "server" path = "tests/server.rs" required-features = ["full"] + +[patch.crates-io] +h2 = { git = "https://github.com/hyperium/h2.git", branch = "rfc8441" } diff --git a/src/client/conn.rs b/src/client/conn.rs index 1273edabf5..2418c9fa83 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -487,6 +487,23 @@ where Poll::Ready(Ok(conn.take().unwrap().into_parts())) }) } + + /// Returns whether the [extended CONNECT protocol][1] is enabled or not. + /// + /// This setting is configured by the server peer by sending the + /// [`SETTINGS_ENABLE_CONNECT_PROTOCOL` parameter][2] in a `SETTINGS` frame. + /// This method returns the currently acknowledged value recieved from the + /// remote. + /// + /// [1]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 + /// [2]: https://datatracker.ietf.org/doc/html/rfc8441#section-3 + #[cfg(feature = "http2")] + pub fn http2_is_extended_connect_protocol_enabled(&self) -> bool { + match self.inner.as_ref().unwrap() { + ProtoClient::H1 { .. } => false, + ProtoClient::H2 { h2 } => h2.is_extended_connect_protocol_enabled(), + } + } } impl Future for Connection diff --git a/src/ext.rs b/src/ext.rs index 10cde75970..8885417a0e 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -1,10 +1,13 @@ -//! HTTP extensions +//! HTTP extensions. use bytes::Bytes; #[cfg(feature = "http1")] use http::header::{HeaderName, IntoHeaderName, ValueIter}; use http::HeaderMap; +#[cfg(feature = "http2")] +pub use h2::ext::Protocol; + /// A map from header names to their original casing as received in an HTTP message. /// /// If an HTTP/1 response `res` is parsed on a connection whose option diff --git a/src/lib.rs b/src/lib.rs index 41a0b37518..f7a93a1959 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ mod cfg; mod common; pub mod body; mod error; -mod ext; +pub mod ext; #[cfg(test)] mod mock; pub mod rt; diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs index 809d8b8505..0e78c09b2c 100644 --- a/src/proto/h2/client.rs +++ b/src/proto/h2/client.rs @@ -204,6 +204,15 @@ where req_rx: ClientRx, } +impl ClientTask +where + B: HttpBody + 'static, +{ + pub(crate) fn is_extended_connect_protocol_enabled(&self) -> bool { + self.h2_tx.is_extended_connect_protocol_enabled() + } +} + impl Future for ClientTask where B: HttpBody + Send + 'static, diff --git a/src/proto/h2/server.rs b/src/proto/h2/server.rs index 94452fb4bb..3278df8e46 100644 --- a/src/proto/h2/server.rs +++ b/src/proto/h2/server.rs @@ -41,6 +41,7 @@ pub(crate) struct Config { pub(crate) initial_conn_window_size: u32, pub(crate) initial_stream_window_size: u32, pub(crate) max_frame_size: u32, + pub(crate) enable_connect_protocol: bool, pub(crate) max_concurrent_streams: Option, #[cfg(feature = "runtime")] pub(crate) keep_alive_interval: Option, @@ -56,6 +57,7 @@ impl Default for Config { initial_conn_window_size: DEFAULT_CONN_WINDOW, initial_stream_window_size: DEFAULT_STREAM_WINDOW, max_frame_size: DEFAULT_MAX_FRAME_SIZE, + enable_connect_protocol: false, max_concurrent_streams: None, #[cfg(feature = "runtime")] keep_alive_interval: None, @@ -117,6 +119,9 @@ where if let Some(max) = config.max_concurrent_streams { builder.max_concurrent_streams(max); } + if config.enable_connect_protocol { + builder.enable_connect_protocol(); + } let handshake = builder.handshake(io); let bdp = if config.adaptive_window { diff --git a/src/server/conn.rs b/src/server/conn.rs index eb9d847788..909d56dbb1 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -555,6 +555,14 @@ impl Http { pub fn http2_max_send_buf_size(&mut self, max: usize) -> &mut Self { assert!(max <= std::u32::MAX as usize); self.h2_builder.max_send_buffer_size = max; + } + + /// Enables the [extended CONNECT protocol]. + /// + /// [extended CONNECT protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 + #[cfg(feature = "http2")] + pub fn http2_enable_connect_protocol(&mut self) -> &mut Self { + self.h2_builder.enable_connect_protocol = true; self } diff --git a/src/server/server.rs b/src/server/server.rs index 9cfb8157bc..40e29c35f1 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -450,6 +450,14 @@ impl Builder { #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub fn http2_max_send_buf_size(mut self, max: usize) -> Self { self.protocol.http2_max_send_buf_size(max); + } + + /// Enables the [extended CONNECT protocol]. + /// + /// [extended CONNECT protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 + #[cfg(feature = "http2")] + pub fn http2_enable_connect_protocol(mut self) -> Self { + self.protocol.http2_enable_connect_protocol(); self }