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}