1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use crate::router::Router; use crate::service::request_service::{RequestService, RequestServiceBuilder}; use hyper::{body::HttpBody, server::conn::AddrStream, service::Service}; use std::convert::Infallible; use std::future::{ready, Ready}; use std::task::{Context, Poll}; /// A [`Service`](https://docs.rs/hyper/0.14.4/hyper/service/trait.Service.html) to process incoming requests. /// /// This `RouterService<B, E>` type accepts two type parameters: `B` and `E`. /// /// * The `B` represents the response body type which will be used by route handlers and the middlewares and this body type must implement /// the [HttpBody](https://docs.rs/hyper/0.14.4/hyper/body/trait.HttpBody.html) trait. For an instance, `B` could be [hyper::Body](https://docs.rs/hyper/0.14.4/hyper/body/struct.Body.html) /// type. /// * The `E` represents any error type which will be used by route handlers and the middlewares. This error type must implement the [std::error::Error](https://doc.rust-lang.org/std/error/trait.Error.html). /// /// # Examples /// /// ```no_run /// use hyper::{Body, Request, Response, Server}; /// use routerify::{Router, RouterService}; /// use std::convert::Infallible; /// use std::net::SocketAddr; /// /// // A handler for "/" page. /// async fn home(_: Request<Body>) -> Result<Response<Body>, Infallible> { /// Ok(Response::new(Body::from("Home page"))) /// } /// /// fn router() -> Router<Body, Infallible> { /// Router::builder() /// .get("/", home) /// .build() /// .unwrap() /// } /// /// #[tokio::main] /// async fn main() { /// let router = router(); /// /// // Create a Service from the router above to handle incoming requests. /// let service = RouterService::new(router).unwrap(); /// /// let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); /// /// // Create a server by passing the created service to `.serve` method. /// let server = Server::bind(&addr).serve(service); /// /// println!("App is running on: {}", addr); /// if let Err(err) = server.await { /// eprintln!("Server error: {}", err); /// } /// } /// ``` #[derive(Debug)] pub struct RouterService<B, E> { builder: RequestServiceBuilder<B, E>, } impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static> RouterService<B, E> { /// Creates a new service with the provided router and it's ready to be used with the hyper [`serve`](https://docs.rs/hyper/0.14.4/hyper/server/struct.Builder.html#method.serve) /// method. pub fn new(router: Router<B, E>) -> crate::Result<RouterService<B, E>> { let builder = RequestServiceBuilder::new(router)?; Ok(RouterService { builder }) } } impl<B: HttpBody + Send + Sync + 'static, E: Into<Box<dyn std::error::Error + Send + Sync>> + 'static> Service<&AddrStream> for RouterService<B, E> { type Response = RequestService<B, E>; type Error = Infallible; type Future = Ready<Result<Self::Response, Self::Error>>; fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { Poll::Ready(Ok(())) } fn call(&mut self, conn: &AddrStream) -> Self::Future { let req_service = self.builder.build(conn.remote_addr()); ready(Ok(req_service)) } }