diff --git a/Cargo.toml b/Cargo.toml index c47ab7e1c..b42f6b429 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ default-tls = ["hyper-tls", "native-tls-crate", "__tls", "tokio-native-tls"] # Enables native-tls specific functionality not available by default. native-tls = ["default-tls"] +native-tls-alpn = ["native-tls", "native-tls-crate/alpn"] native-tls-vendored = ["native-tls", "native-tls-crate/vendored"] rustls-tls = ["rustls-tls-webpki-roots"] @@ -197,7 +198,6 @@ path = "examples/form.rs" [[example]] name = "simple" path = "examples/simple.rs" -required-features = ["deflate"] [[test]] name = "blocking" diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index cf0e547f2..2e80479fb 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -207,6 +207,15 @@ impl ClientBuilder { TlsBackend::Default => { let mut tls = TlsConnector::builder(); + #[cfg(feature = "native-tls-alpn")] + { + if config.http2_only { + tls.request_alpns(&["h2"]); + } else { + tls.request_alpns(&["h2", "http/1.1"]); + } + } + #[cfg(feature = "native-tls")] { tls.danger_accept_invalid_hostnames(!config.hostname_verification); diff --git a/src/connect.rs b/src/connect.rs index 5413acbfd..9f20347bc 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -324,16 +324,20 @@ impl Connector { let mut http = hyper_tls::HttpsConnector::from((http, tls_connector)); let io = http.call(dst).await?; - if let hyper_tls::MaybeHttpsStream::Https(stream) = &io { + if let hyper_tls::MaybeHttpsStream::Https(stream) = io { if !self.nodelay { stream.get_ref().get_ref().get_ref().set_nodelay(false)?; } + Ok(Conn { + inner: self.verbose.wrap(NativeTlsConn { inner: stream }), + is_proxy, + }) + } else { + Ok(Conn { + inner: self.verbose.wrap(io), + is_proxy, + }) } - - Ok(Conn { - inner: self.verbose.wrap(io), - is_proxy, - }) } #[cfg(feature = "__rustls")] Inner::RustlsTls { http, tls, .. } => { @@ -686,6 +690,21 @@ mod native_tls_conn { } impl Connection for NativeTlsConn { + #[cfg(feature = "native-tls-alpn")] + fn connected(&self) -> Connected { + match self.inner.get_ref().negotiated_alpn().ok() { + Some(Some(alpn_protocol)) if alpn_protocol == b"h2" => self + .inner + .get_ref() + .get_ref() + .get_ref() + .connected() + .negotiated_h2(), + _ => self.inner.get_ref().get_ref().get_ref().connected(), + } + } + + #[cfg(not(feature = "native-tls-alpn"))] fn connected(&self) -> Connected { self.inner.get_ref().get_ref().get_ref().connected() } diff --git a/src/lib.rs b/src/lib.rs index f8b4c745d..0bdaf17b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,6 +170,7 @@ //! over HTTPS. //! - **native-tls**: Enables TLS functionality provided by `native-tls`. //! - **native-tls-vendored**: Enables the `vendored` feature of `native-tls`. +//! - **native-tls-alpn**: Enables the `alpn` feature of `native-tls`. //! - **rustls-tls**: Enables TLS functionality provided by `rustls`. //! Equivalent to `rustls-tls-webpki-roots`. //! - **rustls-tls-manual-roots**: Enables TLS functionality provided by `rustls`,