conduit_hyper/
service.rs

1use std::future::Future;
2use std::net::SocketAddr;
3use std::sync::Arc;
4
5use hyper::{service, Body, Request, Response};
6
7mod blocking_handler;
8mod error;
9
10pub use blocking_handler::BlockingHandler;
11pub use error::ServiceError;
12
13/// A builder for a `hyper::Service`.
14#[derive(Debug)]
15pub struct Service;
16
17impl Service {
18    /// Turn a conduit handler into a `Service` which can be bound to a `hyper::Server`.
19    ///
20    /// The returned service can be built into a `hyper::Server` using `make_service_fn` and
21    /// capturing the socket `remote_addr`.
22    ///
23    /// ```no_run
24    /// # use std::sync::Arc;
25    /// # use conduit_hyper::{BlockingHandler, Service};
26    /// # use conduit::{box_error, Body, Handler, HandlerResult, RequestExt, Response};
27    /// #
28    /// # struct Endpoint();
29    /// # impl Handler for Endpoint {
30    /// #     fn call(&self, _: &mut dyn RequestExt) -> HandlerResult {
31    /// #         Response::builder().body(Body::empty()).map_err(box_error)
32    /// #     }
33    /// # }
34    /// # let app = Endpoint();
35    /// let handler = Arc::new(BlockingHandler::new(app));
36    /// let make_service =
37    ///     hyper::service::make_service_fn(move |socket: &hyper::server::conn::AddrStream| {
38    ///         let addr = socket.remote_addr();
39    ///         let handler = handler.clone();
40    ///         async move { Service::from_blocking(handler, addr) }
41    ///     });
42    ///
43    /// # let port = 0;
44    /// let addr = ([127, 0, 0, 1], port).into();
45    /// let server = hyper::Server::bind(&addr).serve(make_service);
46    /// ```
47    pub fn from_blocking<H: conduit::Handler>(
48        handler: Arc<BlockingHandler<H>>,
49        remote_addr: SocketAddr,
50    ) -> Result<
51        impl tower_service::Service<
52            Request<Body>,
53            Response = Response<Body>,
54            Error = ServiceError,
55            Future = impl Future<Output = Result<Response<Body>, ServiceError>> + Send + 'static,
56        >,
57        ServiceError,
58    > {
59        Ok(service::service_fn(move |request: Request<Body>| {
60            handler.clone().blocking_handler(request, remote_addr)
61        }))
62    }
63}