//! Utilities used to interact with the Tower ecosystem. //! //! This module provides `Connect` which hook-ins into the Tower ecosystem. use std::error::Error as StdError; use std::future::Future; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; use tracing::debug; #[cfg_attr(feature = "deprecated", allow(deprecated))] use super::conn::{Builder, SendRequest}; use crate::{ body::HttpBody, service::{MakeConnection, Service}, }; /// Creates a connection via `SendRequest`. /// /// This accepts a `hyper::client::conn::Builder` and provides /// a `MakeService` implementation to create connections from some /// target `T`. #[derive(Debug)] pub struct Connect { inner: C, #[cfg_attr(feature = "deprecated", allow(deprecated))] builder: Builder, _pd: PhantomData, } impl Connect { /// Create a new `Connect` with some inner connector `C` and a connection /// builder. #[cfg_attr(feature = "deprecated", allow(deprecated))] pub fn new(inner: C, builder: Builder) -> Self { Self { inner, builder, _pd: PhantomData, } } } impl Service for Connect where C: MakeConnection, C::Connection: Unpin + Send + 'static, C::Future: Send + 'static, C::Error: Into> + Send, B: HttpBody + Unpin + Send + 'static, B::Data: Send + Unpin, B::Error: Into>, { #[cfg_attr(feature = "deprecated", allow(deprecated))] type Response = SendRequest; type Error = crate::Error; type Future = Pin> + Send + 'static>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner .poll_ready(cx) .map_err(|e| crate::Error::new(crate::error::Kind::Connect).with(e.into())) } fn call(&mut self, req: T) -> Self::Future { let builder = self.builder.clone(); let io = self.inner.make_connection(req); let fut = async move { match io.await { Ok(io) => match builder.handshake(io).await { Ok((sr, conn)) => { #[cfg_attr(feature = "deprecated", allow(deprecated))] builder.exec.execute(async move { if let Err(e) = conn.await { debug!("connection error: {:?}", e); } }); Ok(sr) } Err(e) => Err(e), }, Err(e) => { let err = crate::Error::new(crate::error::Kind::Connect).with(e.into()); Err(err) } } }; Box::pin(fut) } }