spacegate_kernel/helper_layers/
route.rs1use std::{convert::Infallible, ops::Index};
2
3use futures_util::future::BoxFuture;
4pub use hyper::http::request::Parts;
5use hyper::{Request, Response};
6
7use crate::{extension::Matched, SgBody};
8
9pub trait Router: Clone {
10 type Index: Clone;
11 fn route(&self, req: &mut Request<SgBody>) -> Option<Self::Index>;
12}
13
14#[derive(Debug, Clone)]
15pub struct RouterService<S, R, F>
16where
17 R: Router,
18{
19 services: S,
20 fallback: F,
21 router: R,
22}
23
24impl<S, R, F> RouterService<S, R, F>
25where
26 R: Router,
27 S: Index<R::Index>,
28{
29 pub fn new(services: S, router: R, fallback: F) -> Self {
30 Self { services, router, fallback }
31 }
32}
33
34impl<S, R, F> hyper::service::Service<Request<SgBody>> for RouterService<S, R, F>
35where
36 R: Router + Send + Sync + 'static,
37 R::Index: Send + Sync + 'static + Clone,
38 S: Index<R::Index>,
39 S::Output: hyper::service::Service<Request<SgBody>, Response = Response<SgBody>, Error = Infallible> + Send + 'static,
40 F: hyper::service::Service<Request<SgBody>, Response = Response<SgBody>, Error = Infallible> + Send + 'static,
41 <F as hyper::service::Service<hyper::Request<SgBody>>>::Future: std::marker::Send,
42 <S::Output as hyper::service::Service<hyper::Request<SgBody>>>::Future: std::marker::Send,
43{
44 type Error = Infallible;
45 type Response = Response<SgBody>;
46 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
47 fn call(&self, mut req: Request<SgBody>) -> Self::Future {
49 let fut: Self::Future = if let Some(index) = self.router.route(&mut req) {
50 req.extensions_mut().insert(Matched {
51 index: index.clone(),
52 router: self.router.clone(),
53 });
54 let fut = self.services.index(index).call(req);
55 Box::pin(fut)
56 } else {
57 let fut = self.fallback.call(req);
58 Box::pin(fut)
59 };
60 fut
61 }
62}