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())
}
}