diff --git a/Cargo.toml b/Cargo.toml index 2b8b6e088..a59c53601 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,6 @@ hyper = "1" hyper-util = "0.1.6" linked_hash_set = "0.1" openssl-macros = "0.1.1" -tower = "0.4" +tower = { version = "0.4", default-features = false, features = ["util"] } tower-layer = "0.3" tower-service = "0.3" diff --git a/hyper-boring/Cargo.toml b/hyper-boring/Cargo.toml index e8c833fd4..e62395347 100644 --- a/hyper-boring/Cargo.toml +++ b/hyper-boring/Cargo.toml @@ -30,6 +30,7 @@ linked_hash_set = { workspace = true } boring = { workspace = true, default-features = false } tokio = { workspace = true } tokio-boring = { workspace = true, default-features = false } +tower = { workspace = true } tower-layer = { workspace = true } tower-service = { workspace = true } diff --git a/hyper-boring/src/v1.rs b/hyper-boring/src/v1.rs index 38b454229..9dd6d7181 100644 --- a/hyper-boring/src/v1.rs +++ b/hyper-boring/src/v1.rs @@ -19,6 +19,9 @@ use std::sync::Arc; use std::task::{Context, Poll}; use std::{io, net}; use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::net::TcpStream; +use tower::util::MapResponse; +use tower::ServiceExt; use tower_layer::Layer; use tower_service::Service; @@ -29,22 +32,27 @@ pub struct HttpsConnector { inner: Inner, } -impl HttpsConnector { +/// Specialized version of [`HttpConnector`] with responses wrapped with +/// [`TokioIo::new`] in order to bring back compatibility with Tokio traits. +pub type TokioHttpConnector = + MapResponse) -> TokioIo>>; + +impl HttpsConnector { /// Creates a a new `HttpsConnector` using default settings. /// /// The Hyper `HttpConnector` is used to perform the TCP socket connection. ALPN is configured to support both /// HTTP/2 and HTTP/1.1. - pub fn new() -> Result, ErrorStack> { + pub fn new() -> Result { let mut http = HttpConnector::new(); http.enforce_http(false); - HttpsLayer::new().map(|l| l.layer(http)) + HttpsLayer::new().map(|l| l.layer(http.map_response(TokioIo::new as _))) } } impl HttpsConnector where - S: Service> + Send, + S: Service + Send, S::Error: Into>, S::Future: Unpin + Send + 'static, T: AsyncRead + AsyncWrite + Connection + Unpin + fmt::Debug + Sync + Send + 'static, @@ -52,6 +60,10 @@ where /// Creates a new `HttpsConnector`. /// /// The session cache configuration of `ssl` will be overwritten. + /// + /// If the provided service's response type does not fit the trait + /// requirements because it is closer to the Hyper ecosystem than the Tokio + /// one, wrapping your responses with [`TokioIo`] should work. pub fn with_connector( http: S, ssl: SslConnectorBuilder, @@ -212,7 +224,7 @@ impl Inner { impl Service for HttpsConnector where - S: Service> + Send, + S: Service + Send, S::Error: Into>, S::Future: Unpin + Send + 'static, T: AsyncRead + AsyncWrite + Connection + Unpin + fmt::Debug + Sync + Send + 'static, @@ -241,7 +253,7 @@ where let connect = self.http.call(uri); let f = async { - let conn = connect.await.map_err(Into::into)?.into_inner(); + let conn = connect.await.map_err(Into::into)?; let Some((inner, uri)) = tls_setup else { return Ok(MaybeHttpsStream::Http(conn)); diff --git a/hyper-boring/tests/v1.rs b/hyper-boring/tests/v1.rs index 1965959f3..ff022b328 100644 --- a/hyper-boring/tests/v1.rs +++ b/hyper-boring/tests/v1.rs @@ -10,6 +10,7 @@ use hyper_util::rt::{TokioExecutor, TokioIo}; use std::convert::Infallible; use std::{io, iter}; use tokio::net::TcpListener; +use tower::ServiceExt; #[tokio::test] async fn google() { @@ -81,7 +82,7 @@ async fn localhost() { let _ = writeln!(&file, "{line}"); }); - let ssl = HttpsConnector::with_connector(connector, ssl).unwrap(); + let ssl = HttpsConnector::with_connector(connector.map_response(TokioIo::new), ssl).unwrap(); let client = Client::builder(TokioExecutor::new()).build::<_, Empty>(ssl); for _ in 0..3 { @@ -142,7 +143,8 @@ async fn alpn_h2() { ssl.set_ca_file("tests/test/root-ca.pem").unwrap(); - let mut ssl = HttpsConnector::with_connector(connector, ssl).unwrap(); + let mut ssl = + HttpsConnector::with_connector(connector.map_response(TokioIo::new), ssl).unwrap(); ssl.set_ssl_callback(|ssl, _| ssl.set_alpn_protos(b"\x02h2\x08http/1.1"));