router_service/unsync/
service.rs1use std::{
2 collections::HashMap,
3 future::Future,
4 pin::Pin,
5 task::{Context, Poll},
6};
7
8use futures_util::{future::LocalBoxFuture, FutureExt};
9use http::{Request, Response, StatusCode};
10use tower::Service;
11
12use crate::unsync::{RouteContext, Router};
13
14impl<Body, Data, Error> Service<Request<Body>> for Router<Body, Data, Error>
15where
16 Body: Default,
17 Data: Clone,
18{
19 type Response = Response<Body>;
20
21 type Error = Error;
22
23 type Future = ResponseFuture<Body, Error>;
24
25 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
26 Poll::Ready(Ok(()))
27 }
28
29 fn call(&mut self, req: Request<Body>) -> Self::Future {
30 let uri = req.uri();
31
32 let inner = self.inner.read().unwrap();
33
34 if let Ok(node) = inner.at(uri.path()) {
35 let route = node.value;
36 let ctx = RouteContext {
37 params: {
38 let mut params = HashMap::with_capacity(node.params.len());
39 for (name, value) in node.params.iter() {
40 params.insert(name.into(), value.into());
41 }
42 params
43 },
44 data: self.data.clone(),
45 };
46
47 if let Some(handler) = route.handlers.get(req.method()) {
48 return ResponseFuture((handler.0)(req, ctx));
49 }
50
51 if let Some(handler) = &route.catchall {
52 return ResponseFuture((handler.0)(req, ctx));
53 }
54 }
55
56 ResponseFuture(Box::pin(async move {
57 Ok(Response::builder()
58 .status(StatusCode::NOT_FOUND)
59 .body(Body::default())
60 .unwrap())
61 }))
62 }
63}
64
65pub struct ResponseFuture<Body, Error>(LocalBoxFuture<'static, Result<Response<Body>, Error>>);
67
68impl<Body, Error> Future for ResponseFuture<Body, Error> {
69 type Output = Result<Response<Body>, Error>;
70
71 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
72 self.0.poll_unpin(cx)
73 }
74}