satex_server/router/
route.rs1use 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}