siderite_core/middleware/
adapt.rs1use crate::body::Body;
5use crate::extract::Request;
6use crate::response::Response;
7use crate::service::RouterService;
8use axum::BoxError;
9use axum::body::HttpBody;
10use bytes::Bytes;
11use std::convert::Infallible;
12use std::future::Future;
13use std::pin::Pin;
14use std::task::{Context, Poll};
15use tower::util::BoxCloneSyncService;
16use tower::{Layer, Service, ServiceExt};
17
18type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
19
20pub type BoxService = BoxCloneSyncService<Request, Response, Infallible>;
22
23#[derive(Clone)]
25pub struct Next {
26 inner: BoxService,
27}
28
29impl Next {
30 pub async fn run(self, req: Request) -> Response {
32 match self.inner.oneshot(req).await {
33 Ok(response) => response,
34 Err(never) => match never {},
35 }
36 }
37}
38
39pub fn from_fn<F, Fut>(f: F) -> FromFnLayer<F>
41where
42 F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
43 Fut: Future<Output = Response> + Send + 'static,
44{
45 FromFnLayer { f }
46}
47
48#[derive(Clone)]
50pub struct FromFnLayer<F> {
51 f: F,
52}
53
54impl<F, Fut> Layer<BoxService> for FromFnLayer<F>
55where
56 F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
57 Fut: Future<Output = Response> + Send + 'static,
58{
59 type Service = BoxService;
60
61 fn layer(&self, inner: BoxService) -> BoxService {
62 BoxService::new(FromFnService {
63 inner,
64 f: self.f.clone(),
65 })
66 }
67}
68
69#[derive(Clone)]
70struct FromFnService<F> {
71 inner: BoxService,
72 f: F,
73}
74
75impl<F, Fut> Service<Request> for FromFnService<F>
76where
77 F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
78 Fut: Future<Output = Response> + Send + 'static,
79{
80 type Response = Response;
81 type Error = Infallible;
82 type Future = BoxFuture<Result<Response, Infallible>>;
83
84 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Infallible>> {
85 Poll::Ready(Ok(()))
86 }
87
88 fn call(&mut self, req: Request) -> Self::Future {
89 let fut = (self.f)(
90 req,
91 Next {
92 inner: self.inner.clone(),
93 },
94 );
95 Box::pin(async move { Ok(fut.await) })
96 }
97}
98
99macro_rules! impl_layer {
102 ($($ty:ty),+ $(,)?) => {$(
103 impl tower::Layer<$crate::middleware::BoxService> for $ty {
104 type Service = $crate::middleware::BoxService;
105
106 fn layer(&self, inner: $crate::middleware::BoxService) -> Self::Service {
107 self.wrap(inner)
108 }
109 }
110 )+};
111}
112pub(crate) use impl_layer;
113
114pub(crate) fn apply_layer<L>(layer: &L, router: axum::Router) -> axum::Router
116where
117 L: Layer<BoxService>,
118 L::Service:
119 Service<Request, Response = Response, Error = Infallible> + Clone + Send + Sync + 'static,
120 <L::Service as Service<Request>>::Future: Send + 'static,
121{
122 let service = layer.layer(BoxService::new(RouterService::new(router)));
123 axum::Router::new().fallback_service(ToEngine { inner: service })
124}
125
126#[derive(Clone)]
128struct ToEngine<S> {
129 inner: S,
130}
131
132impl<S> Service<axum::extract::Request> for ToEngine<S>
133where
134 S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
135 S::Future: Send + 'static,
136{
137 type Response = axum::response::Response;
138 type Error = Infallible;
139 type Future = BoxFuture<Result<Self::Response, Infallible>>;
140
141 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Infallible>> {
142 self.inner.poll_ready(cx)
143 }
144
145 fn call(&mut self, req: axum::extract::Request) -> Self::Future {
146 let fut = self.inner.call(req.map(Body::from_inner));
147 Box::pin(async move { fut.await.map(|r| r.map(Body::into_inner)) })
148 }
149}
150
151#[derive(Clone)]
153pub(crate) struct EngineIn(BoxService);
154
155impl<B> Service<http::Request<B>> for EngineIn
156where
157 B: HttpBody<Data = Bytes> + Send + 'static,
158 B::Error: Into<BoxError>,
159{
160 type Response = http::Response<axum::body::Body>;
161 type Error = Infallible;
162 type Future = BoxFuture<Result<Self::Response, Infallible>>;
163
164 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Infallible>> {
165 self.0.poll_ready(cx)
166 }
167
168 fn call(&mut self, req: http::Request<B>) -> Self::Future {
169 let fut = self
170 .0
171 .call(req.map(|b| Body::from_inner(axum::body::Body::new(b))));
172 Box::pin(async move { fut.await.map(|r| r.map(Body::into_inner)) })
173 }
174}
175
176#[derive(Clone)]
177struct EngineOut<S>(S);
178
179impl<S, B> Service<Request> for EngineOut<S>
180where
181 S: Service<http::Request<axum::body::Body>, Response = http::Response<B>, Error = Infallible>,
182 S::Future: Send + 'static,
183 B: HttpBody<Data = Bytes> + Send + 'static,
184 B::Error: Into<BoxError>,
185{
186 type Response = Response;
187 type Error = Infallible;
188 type Future = BoxFuture<Result<Response, Infallible>>;
189
190 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Infallible>> {
191 self.0.poll_ready(cx)
192 }
193
194 fn call(&mut self, req: Request) -> Self::Future {
195 let fut = self.0.call(req.map(Body::into_inner));
196 Box::pin(async move {
197 fut.await
198 .map(|r| r.map(|b| Body::from_inner(axum::body::Body::new(b))))
199 })
200 }
201}
202
203pub(crate) fn wrap_engine<L, B>(layer: &L, inner: BoxService) -> BoxService
205where
206 L: Layer<EngineIn>,
207 L::Service: Service<http::Request<axum::body::Body>, Response = http::Response<B>, Error = Infallible>
208 + Clone
209 + Send
210 + Sync
211 + 'static,
212 <L::Service as Service<http::Request<axum::body::Body>>>::Future: Send + 'static,
213 B: HttpBody<Data = Bytes> + Send + 'static,
214 B::Error: Into<BoxError>,
215{
216 BoxService::new(EngineOut(layer.layer(EngineIn(inner))))
217}