1use std::future::Future;
2use futures_util::future::BoxFuture;
3use crate::middleware::Middleware;
4use crate::middleware::next::{Next, NextImp};
5use crate::request::Request;
6use crate::request::extract::ExtractFromRequest;
7use crate::response::Response;
8
9pub trait MiddlewareImp: Send + Sync {
10 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>>;
11}
12
13impl<F, Fut> MiddlewareImp for F where
14 F: Fn(Request, Next) -> Fut + Sync + Send,
15 Fut: Future<Output = teo_result::Result<Response>> + Send + 'static {
16 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>> {
17 Box::pin(self(request, next))
18 }
19}
20
21pub(crate) fn empty_middleware() -> Middleware {
22 Middleware::new(|request: Request, next: Next| async move {
23 next.call(request).await
24 })
25}
26
27pub(crate) fn combine_middleware(middlewares: Vec<Middleware>) -> Middleware {
28 match middlewares.len() {
29 0 => empty_middleware(),
30 1 => middlewares.first().unwrap().clone(),
31 2 => join_middleware(middlewares.get(1).unwrap().clone(), middlewares.get(0).unwrap().clone()),
32 _ => {
33 let inner_most = middlewares.first().unwrap().clone();
34 let mut result = join_middleware(middlewares.get(1).unwrap().clone(), inner_most);
35 for (index, middleware) in middlewares.iter().enumerate() {
36 if index >= 2 {
37 result = join_middleware(middleware.clone(), result);
38 }
39 }
40 result
41 }
42 }
43}
44
45fn join_middleware(outer: Middleware, inner: Middleware) -> Middleware {
46 Middleware::new(move |req: Request, next: Next| {
47 let outer = outer.clone();
48 let inner = inner.clone();
49 async move {
50 outer.call(req, Next::new(move |req: Request| {
51 let inner = inner.clone();
52 let next = next.clone();
53 async move {
54 inner.call(req, next).await
55 }
56 })).await
57 }
58 })
59}
60
61pub trait MiddlewareArgument<A>: Send + Sync + 'static {
62 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>>;
63}
64
65impl<A0, F, Fut> MiddlewareArgument<(A0,)> for F where
66 A0: ExtractFromRequest + Send + Sync,
67 F: Fn(A0, Next) -> Fut + Sync + Send + Clone + 'static,
68 Fut: Future<Output = teo_result::Result<Response>> + Send + 'static {
69 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>> {
70 let value: A0 = ExtractFromRequest::extract(&request);
71 Box::pin(self(value, next))
72 }
73}
74
75impl<A0, A1, F, Fut> MiddlewareArgument<(A0, A1)> for F where
76 A0: ExtractFromRequest + Send + Sync,
77 A1: ExtractFromRequest + Send + Sync,
78 F: Fn(A0, A1, Next) -> Fut + Sync + Send + Clone + 'static,
79 Fut: Future<Output = teo_result::Result<Response>> + Send + 'static {
80 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>> {
81 let a0: A0 = ExtractFromRequest::extract(&request);
82 let a1: A1 = ExtractFromRequest::extract(&request);
83 Box::pin(self(a0, a1, next))
84 }
85}
86
87impl<A0, A1, A2, F, Fut> MiddlewareArgument<(A0, A1, A2)> for F where
88 A0: ExtractFromRequest + Send + Sync,
89 A1: ExtractFromRequest + Send + Sync,
90 A2: ExtractFromRequest + Send + Sync,
91 F: Fn(A0, A1, A2, Next) -> Fut + Sync + Send + Clone + 'static,
92 Fut: Future<Output = teo_result::Result<Response>> + Send + 'static {
93 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>> {
94 let a0: A0 = ExtractFromRequest::extract(&request);
95 let a1: A1 = ExtractFromRequest::extract(&request);
96 let a2: A2 = ExtractFromRequest::extract(&request);
97 Box::pin(self(a0, a1, a2, next))
98 }
99}
100
101impl<A0, A1, A2, A3, F, Fut> MiddlewareArgument<(A0, A1, A2, A3)> for F where
102 A0: ExtractFromRequest + Send + Sync,
103 A1: ExtractFromRequest + Send + Sync,
104 A2: ExtractFromRequest + Send + Sync,
105 A3: ExtractFromRequest + Send + Sync,
106 F: Fn(A0, A1, A2, A3, Next) -> Fut + Sync + Send + Clone + 'static,
107 Fut: Future<Output = teo_result::Result<Response>> + Send + 'static {
108 fn call(&self, request: Request, next: Next) -> BoxFuture<'static, teo_result::Result<Response>> {
109 let a0: A0 = ExtractFromRequest::extract(&request);
110 let a1: A1 = ExtractFromRequest::extract(&request);
111 let a2: A2 = ExtractFromRequest::extract(&request);
112 let a3: A3 = ExtractFromRequest::extract(&request);
113 Box::pin(self(a0, a1, a2, a3, next))
114 }
115}