1 //! Utilities used to interact with the Tower ecosystem. 2 //! 3 //! This module provides `Connect` which hook-ins into the Tower ecosystem. 4 5 use std::error::Error as StdError; 6 use std::future::Future; 7 use std::marker::PhantomData; 8 9 use tracing::debug; 10 11 use super::conn::{Builder, SendRequest}; 12 use crate::{ 13 body::HttpBody, 14 common::{task, Pin, Poll}, 15 service::{MakeConnection, Service}, 16 }; 17 18 /// Creates a connection via `SendRequest`. 19 /// 20 /// This accepts a `hyper::client::conn::Builder` and provides 21 /// a `MakeService` implementation to create connections from some 22 /// target `T`. 23 #[derive(Debug)] 24 pub struct Connect<C, B, T> { 25 inner: C, 26 builder: Builder, 27 _pd: PhantomData<fn(T, B)>, 28 } 29 30 impl<C, B, T> Connect<C, B, T> { 31 /// Create a new `Connect` with some inner connector `C` and a connection 32 /// builder. new(inner: C, builder: Builder) -> Self33 pub fn new(inner: C, builder: Builder) -> Self { 34 Self { 35 inner, 36 builder, 37 _pd: PhantomData, 38 } 39 } 40 } 41 42 impl<C, B, T> Service<T> for Connect<C, B, T> 43 where 44 C: MakeConnection<T>, 45 C::Connection: Unpin + Send + 'static, 46 C::Future: Send + 'static, 47 C::Error: Into<Box<dyn StdError + Send + Sync>> + Send, 48 B: HttpBody + Unpin + Send + 'static, 49 B::Data: Send + Unpin, 50 B::Error: Into<Box<dyn StdError + Send + Sync>>, 51 { 52 type Response = SendRequest<B>; 53 type Error = crate::Error; 54 type Future = 55 Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>; 56 poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>57 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> { 58 self.inner 59 .poll_ready(cx) 60 .map_err(|e| crate::Error::new(crate::error::Kind::Connect).with(e.into())) 61 } 62 call(&mut self, req: T) -> Self::Future63 fn call(&mut self, req: T) -> Self::Future { 64 let builder = self.builder.clone(); 65 let io = self.inner.make_connection(req); 66 67 let fut = async move { 68 match io.await { 69 Ok(io) => match builder.handshake(io).await { 70 Ok((sr, conn)) => { 71 builder.exec.execute(async move { 72 if let Err(e) = conn.await { 73 debug!("connection error: {:?}", e); 74 } 75 }); 76 Ok(sr) 77 } 78 Err(e) => Err(e), 79 }, 80 Err(e) => { 81 let err = crate::Error::new(crate::error::Kind::Connect).with(e.into()); 82 Err(err) 83 } 84 } 85 }; 86 87 Box::pin(fut) 88 } 89 } 90