actix_state_guards/
middleware.rs

1use crate::Guard as GuardTrait;
2
3use std::marker::PhantomData;
4use std::rc::Rc;
5use std::{future::Future, pin::Pin};
6
7use actix_web::body::MessageBody;
8use actix_web::dev::{forward_ready, Service as ServiceTrait, ServiceRequest, ServiceResponse};
9use actix_web::{Error as ActixWebError, FromRequest, ResponseError};
10
11pub struct StateGuardMiddleware<Service, Guard, Args, Error> {
12    service: Rc<Service>,
13    guard: Rc<Guard>,
14    args_marker: PhantomData<Args>,
15    error_marker: PhantomData<Error>,
16}
17
18impl<Service, Guard, Args, Error> StateGuardMiddleware<Service, Guard, Args, Error> {
19    pub(crate) fn new(
20        guard: Rc<Guard>,
21        service: Service,
22    ) -> StateGuardMiddleware<Service, Guard, Args, Error> {
23        Self {
24            guard,
25            service: Rc::new(service),
26            args_marker: PhantomData,
27            error_marker: PhantomData,
28        }
29    }
30}
31
32impl<Service, Body, Guard, Args, Error> ServiceTrait<ServiceRequest>
33    for StateGuardMiddleware<Service, Guard, Args, Error>
34where
35    Service: ServiceTrait<ServiceRequest, Response = ServiceResponse<Body>, Error = ActixWebError>
36        + 'static,
37    Body: MessageBody,
38    Guard: GuardTrait<Args, Error>,
39    Error: ResponseError + 'static,
40    Args: FromRequest,
41{
42    type Response = Service::Response;
43
44    type Error = Service::Error;
45
46    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
47
48    forward_ready!(service);
49
50    fn call(&self, mut req: ServiceRequest) -> Self::Future {
51        let service = Rc::clone(&self.service);
52        let guard = Rc::clone(&self.guard);
53
54        Box::pin(async move {
55            match guard.call_guard_with_service_request(&mut req).await {
56                Ok(()) => service.call(req).await,
57                Err(err) => Err(err.into()),
58            }
59        })
60    }
61}