1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
//! State driven middleware to enable attachment of values to request state. //! //! This module provides generics to enable attaching (appropriate) values to //! the state of a request, through the use of `Middleware`. Middleware can //! be created via `StateMiddleware::with`, with the provided value being the //! value to attach to the request state. use crate::handler::HandlerFuture; use crate::middleware::{Middleware, NewMiddleware}; use crate::state::{State, StateData}; use std::panic::RefUnwindSafe; use std::pin::Pin; /// Middleware binding for generic types to enable easy shared state. /// /// This acts as nothing more than a `Middleware` instance which will /// attach a generic type to a request `State`, however it removes a /// barrier for users to Gotham who might not know the internals. /// /// The generic types inside this struct can (and will) be cloned /// often, so wrap your expensive types in reference counts as needed. #[derive(Clone)] pub struct StateMiddleware<T> where T: Clone + RefUnwindSafe + StateData + Sync, { t: T, } /// Main implementation. impl<T> StateMiddleware<T> where T: Clone + RefUnwindSafe + StateData + Sync, { /// Creates a new middleware binding, taking ownership of the state data. pub fn new(t: T) -> Self { Self { t } } } /// `Middleware` trait implementation. impl<T> Middleware for StateMiddleware<T> where T: Clone + RefUnwindSafe + StateData + Sync, { /// Attaches the inner generic value to the request state. /// /// This will enable the `Handler` to borrow the value directly from the state. fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>> where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>, { state.put(self.t); chain(state) } } /// `NewMiddleware` trait implementation. impl<T> NewMiddleware for StateMiddleware<T> where T: Clone + RefUnwindSafe + StateData + Sync, { type Instance = Self; /// Clones the current middleware to a new instance. fn new_middleware(&self) -> anyhow::Result<Self::Instance> { Ok(self.clone()) } }