Skip to main content

satex_server/router/
route.rs

1use async_trait::async_trait;
2use bytes::Bytes;
3use futures::future::LocalBoxFuture;
4use http::request::Parts;
5use http::{Request, Response, StatusCode};
6use satex_core::body::Body;
7use satex_core::{BoxError, Error};
8use satex_layer::ArcRouteLayer;
9use satex_matcher::{ArcRouteMatcher, RouteMatcher};
10use satex_service::RouteService;
11use std::sync::Arc;
12use std::task::{Context, Poll};
13use tower::{service_fn, Layer, Service};
14
15#[derive(Clone)]
16pub struct Route {
17    id: Arc<str>,
18    matchers: Arc<[ArcRouteMatcher]>,
19    service: RouteService,
20}
21
22impl Route {
23    pub fn builder() -> Builder {
24        Builder::default()
25    }
26
27    pub fn id(&self) -> &str {
28        self.id.as_ref()
29    }
30}
31
32pub struct Builder {
33    id: String,
34    matchers: Vec<ArcRouteMatcher>,
35    layers: Vec<ArcRouteLayer>,
36    service: RouteService,
37}
38
39impl Default for Builder {
40    fn default() -> Self {
41        Self {
42            id: String::default(),
43            matchers: Vec::default(),
44            layers: Vec::default(),
45            service: RouteService::new(service_fn(service_unavailable)),
46        }
47    }
48}
49
50impl Builder {
51    pub fn id(mut self, id: impl Into<String>) -> Self {
52        self.id = id.into();
53        self
54    }
55
56    pub fn service<S, E, ResBody>(mut self, service: S) -> Self
57    where
58        S: Service<Request<Body>, Response=Response<ResBody>, Error=E>
59            + Clone
60            + Send
61            + Sync
62            + 'static,
63        E: Into<BoxError>,
64        ResBody: http_body::Body<Data = Bytes> + Send + 'static,
65        ResBody::Error: Into<BoxError>,
66    {
67        self.service = RouteService::new(service);
68        self
69    }
70
71    pub fn layer<S, L, E, ResBody>(mut self, layer: L) -> Self
72    where
73        S: Service<Request<Body>, Response=Response<ResBody>, Error=E>
74            + Clone
75            + Send
76            + Sync
77            + 'static,
78        E: Into<BoxError>,
79        L: Layer<RouteService, Service = S> + Send + Sync + 'static,
80        ResBody: http_body::Body<Data = Bytes> + Send + 'static,
81        ResBody::Error: Into<BoxError>,
82    {
83        self.layers.push(ArcRouteLayer::new(layer));
84        self
85    }
86
87    pub fn matcher<M>(mut self, matcher: M) -> Self
88    where
89        M: RouteMatcher + Send + Sync + 'static,
90    {
91        self.matchers.push(ArcRouteMatcher::new(matcher));
92        self
93    }
94
95    pub fn build(self) -> Route {
96        let service = self
97            .layers
98            .iter()
99            .fold(RouteService::new(self.service), |service, layer| {
100                layer.layer(service)
101            });
102        Route {
103            id: Arc::from(self.id),
104            matchers: Arc::from(self.matchers),
105            service,
106        }
107    }
108}
109
110async fn service_unavailable(_: Request<Body>) -> Result<Response<Body>, Error> {
111    let mut response = Response::new(Body::empty());
112    *response.status_mut() = StatusCode::SERVICE_UNAVAILABLE;
113    Ok(response)
114}
115
116#[async_trait]
117impl RouteMatcher for Route {
118    async fn matches(&self, parts: &mut Parts) -> satex_core::Result<bool> {
119        for matcher in self.matchers.iter() {
120            match matcher.matches(parts).await {
121                Ok(true) => continue,
122                Ok(false) => return Ok(false),
123                Err(e) => return Err(e),
124            }
125        }
126        Ok(true)
127    }
128}
129
130impl<ReqBody> Service<Request<ReqBody>> for Route
131where
132    ReqBody: http_body::Body<Data = Bytes> + Send + 'static,
133    ReqBody::Error: Into<BoxError>,
134{
135    type Response = Response<Body>;
136    type Error = Error;
137    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
138
139    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
140        <RouteService as Service<Request<ReqBody>>>::poll_ready(&mut self.service, cx)
141    }
142
143    fn call(&mut self, request: Request<ReqBody>) -> Self::Future {
144        self.service.call(request)
145    }
146}