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}