1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//! The client portion of `tower-hyper`. //! //! The client module contains three main utiliteies client, connection //! and connect. Connection and Connect are designed to be used together //! where as Client is a thicker client designed to be used by itself. There //! is less control over driving the inner service compared to Connection. The //! other difference is that Connection is a lower level connection, so there is no //! connection pooling etc, that is the job of the services that wrap it. //! //! # Client Usage //! //! [`Connect`] and [`Connection`] is a lower level connection based client. This means that //! [`Connect`] provides a [`MakeService`] interface that produces [`Connection`]'s. This //! is designed to be used in conjunction with [`tower-http`] and its set of utilities. [`Connect`] //! takes a [`MakeConnection`] that is used to provide the underlying transport. This allows one //! to create a TLS secured transport for example or use udp. //! //! [`Client`] just wraps hyper's [`hyper::Client`] and provides a simple [`Service`] interface. //! //! [`Connect`]: ./struct.Connect.html //! [`Connection`]: ./struct.Connection.html //! [`MakeService`]: ../../tower-util/trait.MakeService.html //! [`Serivce`]: ../../tower_service/trait.Service.html //! [`tower-http`]: https://github.com/tower-rs/tower-http //! [`Client`]: ./struct.Client.html //! [`hyper::Client`]: ../../hyper/struct.Client.html mod connect; mod connection; mod future; pub use self::connect::{Connect, ConnectError}; pub use self::connection::Connection; use self::future::ResponseFuture; pub use hyper::client::conn::Builder; use crate::body::{Body, LiftBody}; use futures::{Async, Poll}; use http_body::Body as HttpBody; use hyper::{ client::connect::Connect as HyperConnect, client::{self, HttpConnector}, Request, Response, }; use tower_service::Service; /// The client wrapp for `hyper::Client` /// /// The generics `C` and `B` are 1-1 with the generic /// types within `hyper::Client`. #[derive(Clone, Debug)] pub struct Client<C, B> { inner: hyper::Client<C, LiftBody<B>>, } impl<B> Client<HttpConnector, B> where B: HttpBody + Send + 'static, B::Data: Send, B::Error: Into<crate::Error>, { /// Create a new client, using the default hyper settings pub fn new() -> Self { let inner = hyper::Client::builder().build_http(); Client { inner } } } impl<C, B> Client<C, B> { /// Create a new client by providing the inner `hyper::Client` /// /// ## Example /// /// The existing default is: ///``` /// use http::Request; /// use tower_hyper::client::Client; /// use tower_service::Service; /// /// let inner = hyper::Client::builder().build_http(); /// let mut client = Client::with_client(inner); /// let _ = client.call(Request::new(vec![0, 1, 2])); /// ```` /// which returns a `Client<HttpConnector, B>` for any B: `HttpBody`. pub fn with_client(inner: hyper::Client<C, LiftBody<B>>) -> Self { Self { inner } } } impl<C, B> Service<Request<B>> for Client<C, B> where C: HyperConnect + Sync + 'static, C::Transport: 'static, C::Future: 'static, B: HttpBody + Send + 'static, B::Data: Send, B::Error: Into<crate::Error>, { type Response = Response<Body>; type Error = hyper::Error; type Future = ResponseFuture<client::ResponseFuture>; /// Poll to see if the service is ready, since `hyper::Client` /// already handles this internally this will always return ready fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } /// Send the sepcficied request to the inner `hyper::Client` fn call(&mut self, req: Request<B>) -> Self::Future { let inner = self.inner.request(req.map(LiftBody::from)); ResponseFuture { inner } } }