Skip to main content

rama_http/layer/validate_request/
validate_fn.rs

1use super::ValidateRequest;
2use crate::{Request, Response};
3use std::marker::PhantomData;
4
5/// Trait for validating requests.
6pub trait ValidateRequestFn<B, A>: Send + Sync + 'static {
7    /// The body type used for responses to unvalidated requests.
8    type ResponseBody;
9
10    /// Validate the request.
11    ///
12    /// If `Ok(())` is returned then the request is allowed through, otherwise not.
13    fn call(
14        &self,
15        request: Request<B>,
16    ) -> impl Future<Output = Result<Request<B>, Response<Self::ResponseBody>>> + Send + '_;
17}
18
19impl<B, F, Fut, ResBody> ValidateRequestFn<B, ()> for F
20where
21    B: Send + 'static,
22    ResBody: Send + 'static,
23    F: Fn() -> Fut + Send + Sync + 'static,
24    Fut: Future<Output = Result<(), Response<ResBody>>> + Send + 'static,
25{
26    type ResponseBody = ResBody;
27
28    async fn call(&self, req: Request<B>) -> Result<Request<B>, Response<Self::ResponseBody>> {
29        match self().await {
30            Ok(_) => Ok(req),
31            Err(res) => Err(res),
32        }
33    }
34}
35
36impl<B, F, Fut, ResBody> ValidateRequestFn<B, ((), Request<B>)> for F
37where
38    B: Send + 'static,
39    ResBody: Send + 'static,
40    F: Fn(Request<B>) -> Fut + Send + Sync + 'static,
41    Fut: Future<Output = Result<Request<B>, Response<ResBody>>> + Send + 'static,
42{
43    type ResponseBody = ResBody;
44
45    async fn call(&self, req: Request<B>) -> Result<Request<B>, Response<Self::ResponseBody>> {
46        match self(req).await {
47            Ok(req) => Ok(req),
48            Err(res) => Err(res),
49        }
50    }
51}
52
53/// The public wrapper type for [`ValidateRequestFn`].
54pub struct BoxValidateRequestFn<F, A> {
55    f: F,
56    _marker: PhantomData<A>,
57}
58
59impl<F, A> BoxValidateRequestFn<F, A> {
60    /// Create a new [`BoxValidateRequestFn`].
61    pub const fn new(f: F) -> Self {
62        Self {
63            f,
64            _marker: PhantomData,
65        }
66    }
67}
68
69impl<F, A> Clone for BoxValidateRequestFn<F, A>
70where
71    F: Clone,
72{
73    fn clone(&self) -> Self {
74        Self {
75            f: self.f.clone(),
76            _marker: PhantomData,
77        }
78    }
79}
80
81impl<F, A> std::fmt::Debug for BoxValidateRequestFn<F, A>
82where
83    F: std::fmt::Debug,
84{
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.debug_struct("BoxValidateRequestFn")
87            .field("f", &self.f)
88            .finish()
89    }
90}
91
92impl<B, A, F> ValidateRequest<B> for BoxValidateRequestFn<F, A>
93where
94    A: Send + Sync + 'static,
95    F: ValidateRequestFn<B, A>,
96{
97    type ResponseBody = F::ResponseBody;
98
99    fn validate(
100        &self,
101        request: Request<B>,
102    ) -> impl Future<Output = Result<Request<B>, Response<Self::ResponseBody>>> + Send + '_ {
103        self.f.call(request)
104    }
105}