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}