axum_help/filter/
predicate.rs

1use std::{future::Future, sync::Arc};
2
3/// Checks a request synchronously
4///
5///
6/// # Example
7/// ```
8/// # use axum_help::filter::Predicate;
9/// # use http::Response;
10/// # use http::Request;
11/// #
12/// struct CheckService;
13///
14/// impl<ResBody, ReqBody> Predicate<Request<ReqBody>, ResBody> for CheckService
15/// where
16///     ResBody: Default,
17/// {
18///     type Request = Request<ReqBody>;
19///     type Response = Response<ResBody>;
20///
21///     fn check(&mut self, mut request: Request<ReqBody>) -> Result<Self::Request, Self::Response> {
22///         // do something check
23///         Ok(request)   
24///     }
25/// }
26/// ```
27pub trait Predicate<Request> {
28    /// The type of requests returned by [`check`](Predicate::check).
29    ///
30    /// This request is forwarded to the inner service if the predicate
31    /// succeeds.
32    type Request;
33
34    /// The type of response return by [`check`](Predicate::check) if the predicate failed.
35    type Response;
36
37    /// Check whether the given request should be forwarded.
38    ///
39    /// If the future resolves with [`Ok`], the request is forwarded to the inner service.
40    fn check(&self, request: Request) -> Result<Self::Request, Self::Response>;
41}
42
43impl<T, Req, Res, F> Predicate<T> for F
44where
45    F: Fn(T) -> Result<Req, Res>,
46{
47    type Request = Req;
48    type Response = Res;
49
50    fn check(&self, request: T) -> Result<Self::Request, Self::Response> {
51        self(request)
52    }
53}
54
55/// Checks a request asynchronously
56///
57/// # Example
58/// ```
59/// # use axum_help::filter::AsyncPredicate;
60/// # use http::Request;
61/// # use axum::response::Response;
62/// # use std::pin::Pin;
63/// # use std::future::Future;
64/// #
65/// struct CheckService;
66///
67/// impl<ReqBody, ResBody> AsyncPredicate<Request<ReqBody>, ResBody> for CheckService
68/// where
69///     ReqBody: Send + 'static,
70///     ResBody: Default + Send + 'static,
71/// {
72///     type Request = Request<ReqBody>;
73///     type Response = Response<ResBody>;
74///     type Future = Pin<Box<dyn Future<Output = Result<Self::Request, Self::Response>> + Send>>;
75///
76///     fn check(&mut self, request: Request<ReqBody>) -> Self::Future {
77///         Box::pin(async move {
78///             // do something check
79///             Ok(request)
80///         })
81///     }
82/// }
83/// ```
84pub trait AsyncPredicate<R> {
85    /// The type of requests returned by [`check`](AsyncPredicate::check)
86    ///
87    /// This request is forwarded to the inner service if the predicate
88    /// succeeds.
89    type Request;
90
91    /// The type of response return by [`check`](AsyncPredicate::check) if the predicate failed.
92    type Response;
93
94    /// The future returned by [`check`](AsyncPredicate::check)
95    type Future: Future<Output = Result<Self::Request, Self::Response>>;
96
97    /// Check whether the given request should be forwarded.
98    ///
99    /// If the future resolves with [`Ok`], the request is forwarded to the inner service.
100    fn check(&self, request: R) -> Self::Future;
101}
102
103impl<T, Req, Res, U, F> AsyncPredicate<T> for F
104where
105    F: Fn(T) -> U,
106    U: Future<Output = Result<Req, Res>>,
107{
108    type Request = Req;
109    type Response = Res;
110    type Future = U;
111
112    fn check(&self, request: T) -> Self::Future {
113        self(request)
114    }
115}
116
117impl<T, R> AsyncPredicate<R> for Arc<T>
118where
119    T: AsyncPredicate<R>,
120{
121    type Request = T::Request;
122    type Response = T::Response;
123    type Future = T::Future;
124
125    fn check(&self, request: R) -> Self::Future {
126        (**self).check(request)
127    }
128}