hyper_middleware/
service.rs

1//! The Hyper service module.
2//!
3//! It provides a [Hyper Service][`hyper::service::Service`] implementation intended to work with
4//! the `hyper::server::Builder`.
5//!
6//! The service allows to bind a [`Middlewares`][`super::Middlewares`] of middlewares.
7//!
8//! ## Example
9//!
10//! ```rust
11//! use hyper::Server;
12//! use hyper_middleware::{
13//!     async_trait, Body, Handler, Request, Response, Middlewares, Result, Service,
14//! };
15//!
16//! struct Application {}
17//!
18//! #[async_trait]
19//! impl Handler for Application {
20//!     async fn handle(&self, _req: &mut Request) -> Result<Response> {
21//!         // Create a response and send it back to the middlewares chain
22//!         Ok(Response::new(Body::from("¡Hola!")))
23//!     }
24//! }
25//!
26//! #[tokio::main(flavor = "multi_thread")]
27//! async fn main() -> Result {
28//!     let mut middlewares = Middlewares::new(Application {});
29//!
30//!     let service = Service::new(middlewares);
31//!
32//!     let addr = ([127, 0, 0, 1], 8087).into();
33//!     let server = Server::bind(&addr).serve(service);
34//!
35//!     println!("Listening on http://{}", addr);
36//!
37//!     // server.await?;
38//!
39//!     Ok(())
40//! }
41//! ```
42
43use hyper::service::Service as HyperService;
44use std::convert::Infallible;
45use std::future::{ready, Ready};
46use std::task::{Context, Poll};
47
48use self::handler_service::{HandlerService, HandlerServiceBuilder};
49use crate::middleware::Handler;
50use crate::remote_addr::RemoteAddr;
51
52/// A [Hyper Service][`hyper::service::Service`] entry point which hosts a [`Handler`].
53pub struct Service<H> {
54    builder: HandlerServiceBuilder<H>,
55}
56
57impl<H> Service<H>
58where
59    H: Handler,
60{
61    /// Create a new Service instance which will be used when create a Hyper server.
62    pub fn new(handler: H) -> Self {
63        Self {
64            builder: HandlerServiceBuilder::new(handler),
65        }
66    }
67}
68
69impl<H, T> HyperService<&T> for Service<H>
70where
71    H: Handler,
72    T: RemoteAddr + Send + 'static,
73{
74    type Response = HandlerService<H>;
75    type Error = Infallible;
76    type Future = Ready<Result<Self::Response, Self::Error>>;
77
78    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
79        Poll::Ready(Ok(()))
80    }
81
82    fn call(&mut self, conn: &T) -> Self::Future {
83        ready(Ok(self.builder.build(conn.remote_addr())))
84    }
85}
86
87mod handler_service {
88    use std::future::Future;
89    use std::net::SocketAddr;
90    use std::pin::Pin;
91    use std::sync::Arc;
92    use std::task::{Context, Poll};
93
94    use crate::error::{Error, Result};
95    use crate::http::{Request, Response};
96    use crate::middleware::Handler;
97    use crate::service::HyperService;
98
99    pub struct HandlerService<H> {
100        handler: Arc<H>,
101        remote_addr: Option<SocketAddr>,
102    }
103
104    impl<H> HyperService<Request> for HandlerService<H>
105    where
106        H: Handler,
107    {
108        type Response = Response;
109        type Error = Error;
110        type Future = Pin<Box<dyn Future<Output = Result<Response>> + Send + 'static>>;
111
112        fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<()>> {
113            Poll::Ready(Ok(()))
114        }
115
116        fn call(&mut self, mut req: Request) -> Self::Future {
117            if let Some(remote_addr) = self.remote_addr {
118                req.extensions_mut().insert(remote_addr);
119            }
120            let handler = self.handler.clone();
121            Box::pin(async move { handler.handle(&mut req).await })
122        }
123    }
124
125    pub struct HandlerServiceBuilder<H> {
126        handler: Arc<H>,
127    }
128
129    impl<H> HandlerServiceBuilder<H>
130    where
131        H: Handler + Send + Sync + 'static,
132    {
133        pub fn new(handler: H) -> Self {
134            Self {
135                handler: Arc::new(handler),
136            }
137        }
138
139        pub fn build(&self, remote_addr: Option<SocketAddr>) -> HandlerService<H> {
140            HandlerService {
141                handler: self.handler.clone(),
142                remote_addr,
143            }
144        }
145    }
146}