tower_hyper/client/
mod.rs

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