From e87a725bc126859549579d10e2121c6ea07e4847 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:10:12 -0500 Subject: [PATCH 1/7] feat(s2n-tls-hyper): Add support for negotiating HTTP/2 --- .github/workflows/ci_rust.yml | 4 +- bindings/rust/s2n-tls-hyper/Cargo.toml | 13 ++++-- bindings/rust/s2n-tls-hyper/src/stream.rs | 11 ++++- bindings/rust/s2n-tls-hyper/tests/http.rs | 50 ++++++++++++++++++++++- 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci_rust.yml b/.github/workflows/ci_rust.yml index b53c1408da5..a726e612962 100644 --- a/.github/workflows/ci_rust.yml +++ b/.github/workflows/ci_rust.yml @@ -49,10 +49,10 @@ jobs: working-directory: ${{env.ROOT_PATH}} run: cargo test - - name: "Feature Tests: Fingerprint, kTLS, QUIC, and PQ" + - name: "Feature Tests: Fingerprint, kTLS, QUIC, PQ, and http2" working-directory: ${{env.ROOT_PATH}} # Test all features except for FIPS, which is tested separately. - run: cargo test --features unstable-fingerprint,unstable-ktls,quic,pq + run: cargo test --features unstable-fingerprint,unstable-ktls,quic,pq,http2 - name: "Feature Test: Renegotiate" working-directory: ${{env.ROOT_PATH}} diff --git a/bindings/rust/s2n-tls-hyper/Cargo.toml b/bindings/rust/s2n-tls-hyper/Cargo.toml index 8cdf850b3bd..865346a97e7 100644 --- a/bindings/rust/s2n-tls-hyper/Cargo.toml +++ b/bindings/rust/s2n-tls-hyper/Cargo.toml @@ -10,15 +10,22 @@ license = "Apache-2.0" publish = false [features] -default = [] +default = ["http1"] +http1 = ["hyper-util/http1"] +http2 = ["hyper-util/http2", "dep:hashbrown", "dep:tokio-util"] [dependencies] s2n-tls = { version = "=0.3.7", path = "../s2n-tls" } s2n-tls-tokio = { version = "=0.3.7", path = "../s2n-tls-tokio" } hyper = { version = "1" } -hyper-util = { version = "0.1", features = ["client-legacy", "tokio", "http1"] } +hyper-util = { version = "0.1", features = ["client-legacy", "tokio"] } tower-service = { version = "0.3" } -http = { version= "1" } +http = { version = "1" } + +# Newer versions require Rust 1.65, see https://github.com/aws/s2n-tls/issues/4242. +hashbrown = { version = "=0.15.0", optional = true } +# Newer versions require Rust 1.70, see https://github.com/aws/s2n-tls/issues/4395. +tokio-util = { version = "=0.7.11", optional = true } [dev-dependencies] tokio = { version = "1", features = ["macros", "test-util"] } diff --git a/bindings/rust/s2n-tls-hyper/src/stream.rs b/bindings/rust/s2n-tls-hyper/src/stream.rs index 61bc59fe682..5af60c5f067 100644 --- a/bindings/rust/s2n-tls-hyper/src/stream.rs +++ b/bindings/rust/s2n-tls-hyper/src/stream.rs @@ -48,7 +48,16 @@ where { fn connected(&self) -> Connected { match self { - MaybeHttpsStream::Https(stream) => stream.inner().get_ref().connected(), + MaybeHttpsStream::Https(stream) => { + let connected = stream.inner().get_ref().connected(); + let conn = stream.inner().as_ref(); + match conn.application_protocol() { + // Inform hyper that HTTP/2 was negotiated in the ALPN. + #[cfg(feature = "http2")] + Some(b"h2") => connected.negotiated_h2(), + _ => connected, + } + } } } } diff --git a/bindings/rust/s2n-tls-hyper/tests/http.rs b/bindings/rust/s2n-tls-hyper/tests/http.rs index 8a1a8a37243..f49359a99f8 100644 --- a/bindings/rust/s2n-tls-hyper/tests/http.rs +++ b/bindings/rust/s2n-tls-hyper/tests/http.rs @@ -4,7 +4,7 @@ use crate::common::InsecureAcceptAllCertificatesHandler; use bytes::Bytes; use common::echo::serve_echo; -use http::{Method, Request, Uri}; +use http::{Method, Request, Uri, Version}; use http_body_util::{BodyExt, Empty, Full}; use hyper_util::{client::legacy::Client, rt::TokioExecutor}; use s2n_tls::{ @@ -215,3 +215,51 @@ async fn error_matching() -> Result<(), Box> { server_task.abort(); Ok(()) } + +#[tokio::test] +async fn http2() -> Result<(), Box> { + let server_config = { + let mut builder = common::config()?; + builder.set_application_protocol_preference(["h2"])?; + builder.build()? + }; + + for send_h2 in [true, false] { + let client_config = { + let mut builder = common::config()?; + if send_h2 { + builder.set_application_protocol_preference(["h2"])?; + } + builder.build()? + }; + + common::echo::make_echo_request(server_config.clone(), |port| async move { + let connector = HttpsConnector::new(client_config); + let client: Client<_, Empty> = + Client::builder(TokioExecutor::new()).build(connector); + + let uri = Uri::from_str(format!("https://localhost:{}", port).as_str())?; + let response = client.get(uri).await?; + assert_eq!(response.status(), 200); + + // Ensure that HTTP/2 is negotiated when included in the ALPN. + #[cfg(feature = "http2")] + let expected_version = match send_h2 { + true => Version::HTTP_2, + false => Version::HTTP_11, + }; + + // If the http2 feature isn't enabled, then HTTP/1 should be negotiated even if HTTP/2 + // was included in the ALPN. + #[cfg(not(feature = "http2"))] + let expected_version = Version::HTTP_11; + + assert_eq!(response.version(), expected_version); + + Ok(()) + }) + .await?; + } + + Ok(()) +} From 022044480eb533193792c75f7e3c7fd5c97920ba Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:54:08 -0500 Subject: [PATCH 2/7] always attempt http/2 --- .github/workflows/ci_rust.yml | 4 +- bindings/rust/s2n-tls-hyper/Cargo.toml | 10 ++- bindings/rust/s2n-tls-hyper/src/connector.rs | 14 ++++- bindings/rust/s2n-tls-hyper/src/stream.rs | 1 - bindings/rust/s2n-tls-hyper/tests/http.rs | 64 +++++++++++++------- 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci_rust.yml b/.github/workflows/ci_rust.yml index a726e612962..b53c1408da5 100644 --- a/.github/workflows/ci_rust.yml +++ b/.github/workflows/ci_rust.yml @@ -49,10 +49,10 @@ jobs: working-directory: ${{env.ROOT_PATH}} run: cargo test - - name: "Feature Tests: Fingerprint, kTLS, QUIC, PQ, and http2" + - name: "Feature Tests: Fingerprint, kTLS, QUIC, and PQ" working-directory: ${{env.ROOT_PATH}} # Test all features except for FIPS, which is tested separately. - run: cargo test --features unstable-fingerprint,unstable-ktls,quic,pq,http2 + run: cargo test --features unstable-fingerprint,unstable-ktls,quic,pq - name: "Feature Test: Renegotiate" working-directory: ${{env.ROOT_PATH}} diff --git a/bindings/rust/s2n-tls-hyper/Cargo.toml b/bindings/rust/s2n-tls-hyper/Cargo.toml index 865346a97e7..03c71401ed9 100644 --- a/bindings/rust/s2n-tls-hyper/Cargo.toml +++ b/bindings/rust/s2n-tls-hyper/Cargo.toml @@ -10,22 +10,20 @@ license = "Apache-2.0" publish = false [features] -default = ["http1"] -http1 = ["hyper-util/http1"] -http2 = ["hyper-util/http2", "dep:hashbrown", "dep:tokio-util"] +default = [] [dependencies] s2n-tls = { version = "=0.3.7", path = "../s2n-tls" } s2n-tls-tokio = { version = "=0.3.7", path = "../s2n-tls-tokio" } hyper = { version = "1" } -hyper-util = { version = "0.1", features = ["client-legacy", "tokio"] } +hyper-util = { version = "0.1", features = ["client-legacy", "tokio", "http1", "http2"] } tower-service = { version = "0.3" } http = { version = "1" } # Newer versions require Rust 1.65, see https://github.com/aws/s2n-tls/issues/4242. -hashbrown = { version = "=0.15.0", optional = true } +hashbrown = { version = "=0.15.0" } # Newer versions require Rust 1.70, see https://github.com/aws/s2n-tls/issues/4395. -tokio-util = { version = "=0.7.11", optional = true } +tokio-util = { version = "=0.7.11" } [dev-dependencies] tokio = { version = "1", features = ["macros", "test-util"] } diff --git a/bindings/rust/s2n-tls-hyper/src/connector.rs b/bindings/rust/s2n-tls-hyper/src/connector.rs index a160e605471..d4b8aa79f60 100644 --- a/bindings/rust/s2n-tls-hyper/src/connector.rs +++ b/bindings/rust/s2n-tls-hyper/src/connector.rs @@ -41,6 +41,10 @@ where /// /// This API creates an `HttpsConnector` using the default hyper `HttpConnector`. To use an /// existing HTTP connector, use `HttpsConnector::new_with_http()`. + /// + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding + /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new(conn_builder: Builder) -> HttpsConnector { let mut http = HttpConnector::new(); @@ -77,6 +81,10 @@ where /// ``` /// /// `HttpsConnector::new()` can be used to create the HTTP connector automatically. + /// + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding + /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new_with_http(http: Http, conn_builder: Builder) -> HttpsConnector { Self { http, conn_builder } } @@ -118,7 +126,11 @@ where return Box::pin(async move { Err(Error::InvalidScheme) }); } - let builder = self.conn_builder.clone(); + // Attempt to negotiate HTTP/2. + let builder = connection::ModifiedBuilder::new(self.conn_builder.clone(), |conn| { + conn.set_application_protocol_preference([b"h2"]) + }); + let host = req.host().unwrap_or("").to_owned(); let call = self.http.call(req); Box::pin(async move { diff --git a/bindings/rust/s2n-tls-hyper/src/stream.rs b/bindings/rust/s2n-tls-hyper/src/stream.rs index 5af60c5f067..c5440285465 100644 --- a/bindings/rust/s2n-tls-hyper/src/stream.rs +++ b/bindings/rust/s2n-tls-hyper/src/stream.rs @@ -53,7 +53,6 @@ where let conn = stream.inner().as_ref(); match conn.application_protocol() { // Inform hyper that HTTP/2 was negotiated in the ALPN. - #[cfg(feature = "http2")] Some(b"h2") => connected.negotiated_h2(), _ => connected, } diff --git a/bindings/rust/s2n-tls-hyper/tests/http.rs b/bindings/rust/s2n-tls-hyper/tests/http.rs index f49359a99f8..3f22a32952b 100644 --- a/bindings/rust/s2n-tls-hyper/tests/http.rs +++ b/bindings/rust/s2n-tls-hyper/tests/http.rs @@ -218,23 +218,17 @@ async fn error_matching() -> Result<(), Box> { #[tokio::test] async fn http2() -> Result<(), Box> { - let server_config = { - let mut builder = common::config()?; - builder.set_application_protocol_preference(["h2"])?; - builder.build()? - }; - - for send_h2 in [true, false] { - let client_config = { + for expected_http_version in [Version::HTTP_11, Version::HTTP_2] { + let server_config = { let mut builder = common::config()?; - if send_h2 { + if expected_http_version == Version::HTTP_2 { builder.set_application_protocol_preference(["h2"])?; } builder.build()? }; common::echo::make_echo_request(server_config.clone(), |port| async move { - let connector = HttpsConnector::new(client_config); + let connector = HttpsConnector::new(common::config()?.build()?); let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(connector); @@ -242,19 +236,8 @@ async fn http2() -> Result<(), Box> { let response = client.get(uri).await?; assert_eq!(response.status(), 200); - // Ensure that HTTP/2 is negotiated when included in the ALPN. - #[cfg(feature = "http2")] - let expected_version = match send_h2 { - true => Version::HTTP_2, - false => Version::HTTP_11, - }; - - // If the http2 feature isn't enabled, then HTTP/1 should be negotiated even if HTTP/2 - // was included in the ALPN. - #[cfg(not(feature = "http2"))] - let expected_version = Version::HTTP_11; - - assert_eq!(response.version(), expected_version); + // Ensure that HTTP/2 is negotiated when supported by the server. + assert_eq!(response.version(), expected_http_version); Ok(()) }) @@ -263,3 +246,38 @@ async fn http2() -> Result<(), Box> { Ok(()) } + +/// Ensure that HTTP/2 is negotiated, regardless of any pre-configured ALPN values. +#[tokio::test] +async fn config_alpn_ignored() -> Result<(), Box> { + let server_config = { + let mut builder = common::config()?; + builder.set_application_protocol_preference(["h2"])?; + builder.build()? + }; + + common::echo::make_echo_request(server_config, |port| async move { + let client_config = { + let mut builder = common::config()?; + // Set an arbitrary non-HTTP/2 ALPN value. + builder.set_application_protocol_preference([b"http/1.1"])?; + builder.build()? + }; + + let connector = HttpsConnector::new(client_config); + let client: Client<_, Empty> = + Client::builder(TokioExecutor::new()).build(connector); + + let uri = Uri::from_str(format!("https://localhost:{}", port).as_str())?; + let response = client.get(uri).await?; + assert_eq!(response.status(), 200); + + // Ensure that HTTP/2 was negotiated. + assert_eq!(response.version(), Version::HTTP_2); + + Ok(()) + }) + .await?; + + Ok(()) +} From a6cf75a943b42a691a26b5cf2bd102cd81ba75fd Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:02:37 -0500 Subject: [PATCH 3/7] append h2 to ALPN instead of override --- bindings/rust/s2n-tls-hyper/src/connector.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bindings/rust/s2n-tls-hyper/src/connector.rs b/bindings/rust/s2n-tls-hyper/src/connector.rs index d4b8aa79f60..0f34d768829 100644 --- a/bindings/rust/s2n-tls-hyper/src/connector.rs +++ b/bindings/rust/s2n-tls-hyper/src/connector.rs @@ -42,9 +42,10 @@ where /// This API creates an `HttpsConnector` using the default hyper `HttpConnector`. To use an /// existing HTTP connector, use `HttpsConnector::new_with_http()`. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by appending to /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like - /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be sent in addition + /// to "h2". pub fn new(conn_builder: Builder) -> HttpsConnector { let mut http = HttpConnector::new(); @@ -82,9 +83,10 @@ where /// /// `HttpsConnector::new()` can be used to create the HTTP connector automatically. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by appending to /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like - /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be sent in addition + /// to "h2". pub fn new_with_http(http: Http, conn_builder: Builder) -> HttpsConnector { Self { http, conn_builder } } @@ -128,7 +130,7 @@ where // Attempt to negotiate HTTP/2. let builder = connection::ModifiedBuilder::new(self.conn_builder.clone(), |conn| { - conn.set_application_protocol_preference([b"h2"]) + conn.append_application_protocol_preference(b"h2") }); let host = req.host().unwrap_or("").to_owned(); From b8d25ba4c32d9c4a719413b5dbbe1356ea458866 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:13:57 -0500 Subject: [PATCH 4/7] fix pins --- bindings/rust/s2n-tls-hyper/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/rust/s2n-tls-hyper/Cargo.toml b/bindings/rust/s2n-tls-hyper/Cargo.toml index 03c71401ed9..eb86a9ebbb6 100644 --- a/bindings/rust/s2n-tls-hyper/Cargo.toml +++ b/bindings/rust/s2n-tls-hyper/Cargo.toml @@ -20,13 +20,13 @@ hyper-util = { version = "0.1", features = ["client-legacy", "tokio", "http1", " tower-service = { version = "0.3" } http = { version = "1" } -# Newer versions require Rust 1.65, see https://github.com/aws/s2n-tls/issues/4242. -hashbrown = { version = "=0.15.0" } -# Newer versions require Rust 1.70, see https://github.com/aws/s2n-tls/issues/4395. -tokio-util = { version = "=0.7.11" } - [dev-dependencies] tokio = { version = "1", features = ["macros", "test-util"] } http-body-util = "0.1" hyper-util = { version = "0.1", features = ["server"] } bytes = "1" + +# Newer versions require Rust 1.65, see https://github.com/aws/s2n-tls/issues/4242. +hashbrown = { version = "=0.15.0" } +# Newer versions require Rust 1.70, see https://github.com/aws/s2n-tls/issues/4395. +tokio-util = { version = "=0.7.11" } From 8d090e90cc1dda69add571e47f5d14ec2dbebc38 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:56:08 -0500 Subject: [PATCH 5/7] Revert "append h2 to ALPN instead of override" This reverts commit a6cf75a943b42a691a26b5cf2bd102cd81ba75fd. --- bindings/rust/s2n-tls-hyper/src/connector.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bindings/rust/s2n-tls-hyper/src/connector.rs b/bindings/rust/s2n-tls-hyper/src/connector.rs index 0f34d768829..d4b8aa79f60 100644 --- a/bindings/rust/s2n-tls-hyper/src/connector.rs +++ b/bindings/rust/s2n-tls-hyper/src/connector.rs @@ -42,10 +42,9 @@ where /// This API creates an `HttpsConnector` using the default hyper `HttpConnector`. To use an /// existing HTTP connector, use `HttpsConnector::new_with_http()`. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by appending to + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like - /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be sent in addition - /// to "h2". + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new(conn_builder: Builder) -> HttpsConnector { let mut http = HttpConnector::new(); @@ -83,10 +82,9 @@ where /// /// `HttpsConnector::new()` can be used to create the HTTP connector automatically. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by appending to + /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like - /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be sent in addition - /// to "h2". + /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new_with_http(http: Http, conn_builder: Builder) -> HttpsConnector { Self { http, conn_builder } } @@ -130,7 +128,7 @@ where // Attempt to negotiate HTTP/2. let builder = connection::ModifiedBuilder::new(self.conn_builder.clone(), |conn| { - conn.append_application_protocol_preference(b"h2") + conn.set_application_protocol_preference([b"h2"]) }); let host = req.host().unwrap_or("").to_owned(); From 0afa5ba78c00f589b315db01dc20187ec55ea93f Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:56:09 -0500 Subject: [PATCH 6/7] also send other HTTP versions in ALPN --- bindings/rust/s2n-tls-hyper/src/connector.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/bindings/rust/s2n-tls-hyper/src/connector.rs b/bindings/rust/s2n-tls-hyper/src/connector.rs index d4b8aa79f60..d8dab5bc9e9 100644 --- a/bindings/rust/s2n-tls-hyper/src/connector.rs +++ b/bindings/rust/s2n-tls-hyper/src/connector.rs @@ -126,9 +126,20 @@ where return Box::pin(async move { Err(Error::InvalidScheme) }); } - // Attempt to negotiate HTTP/2. + // Attempt to negotiate HTTP/2 by including it in the ALPN. Other supported HTTP versions + // are also included to prevent the server from rejecting the TLS connection due to an + // unsupported ALPN: + // + // https://datatracker.ietf.org/doc/html/rfc7301#section-3.2 + // In the event that the server supports no + // protocols that the client advertises, then the server SHALL respond + // with a fatal "no_application_protocol" alert. let builder = connection::ModifiedBuilder::new(self.conn_builder.clone(), |conn| { - conn.set_application_protocol_preference([b"h2"]) + conn.set_application_protocol_preference([ + b"h2".to_vec(), + b"http/1.1".to_vec(), + b"http/1.0".to_vec(), + ]) }); let host = req.host().unwrap_or("").to_owned(); From a90e03a217c11f9449a6b02fd34af5da2bd29516 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:19:01 -0500 Subject: [PATCH 7/7] fixes --- bindings/rust/s2n-tls-hyper/src/connector.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/rust/s2n-tls-hyper/src/connector.rs b/bindings/rust/s2n-tls-hyper/src/connector.rs index 4d19f847d82..ea5670d62f0 100644 --- a/bindings/rust/s2n-tls-hyper/src/connector.rs +++ b/bindings/rust/s2n-tls-hyper/src/connector.rs @@ -42,8 +42,8 @@ where /// This API creates an `HttpsConnector` using the default hyper `HttpConnector`. To use an /// existing HTTP connector, use `HttpsConnector::new_with_http()`. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding - /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like + /// Note that s2n-tls-hyper will override the ALPN extension to negotiate HTTP. Any ALPN values + /// configured on `conn_builder` with APIs like /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new(conn_builder: Builder) -> HttpsConnector { let mut http = HttpConnector::new(); @@ -82,8 +82,8 @@ where /// /// `HttpsConnector::new()` can be used to create the HTTP connector automatically. /// - /// Note that the HttpsConnector will automatically attempt to negotiate HTTP/2 by overriding - /// the ALPN extension. Any ALPN values configured on `conn_builder` with APIs like + /// Note that s2n-tls-hyper will override the ALPN extension to negotiate HTTP. Any ALPN values + /// configured on `conn_builder` with APIs like /// `s2n_tls::config::Builder::set_application_protocol_preference()` will be ignored. pub fn new_with_http(http: Http, conn_builder: Builder) -> HttpsConnector { Self { http, conn_builder } @@ -126,9 +126,9 @@ where return Box::pin(async move { Err(Error::InvalidScheme) }); } - // Attempt to negotiate HTTP/2 by including it in the ALPN. Other supported HTTP versions - // are also included to prevent the server from rejecting the TLS connection due to an - // unsupported ALPN: + // Attempt to negotiate HTTP/2 by including it in the ALPN extension. Other supported HTTP + // versions are also included to prevent the server from rejecting the TLS connection if + // HTTP/2 isn't supported: // // https://datatracker.ietf.org/doc/html/rfc7301#section-3.2 // In the event that the server supports no