Trait gotham::middleware::Middleware
source · [−]pub trait Middleware {
fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where
Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
Self: Sized;
}
Expand description
Middleware
has the opportunity to provide additional behaviour to the Request
/ Response
interaction. For example:
- The request can be halted due to some unmet precondition;
- Processing the request can be delayed until some other action has completed;
- Middleware-specific state data can be recorded in the
State
struct for use elsewhere; - The returned future can be manipulated via continuations to provide additional behaviour after the request completes.
Examples
Taking no action, and immediately passing the Request
through to the rest of the application:
#[derive(NewMiddleware, Copy, Clone)]
struct NoopMiddleware;
impl Middleware for NoopMiddleware {
fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static
{
chain(state)
}
}
Recording a piece of state data before passing the request through:
#[derive(NewMiddleware, Copy, Clone)]
struct MiddlewareWithStateData;
#[derive(StateData)]
struct MiddlewareStateData {
i: i32,
}
impl Middleware for MiddlewareWithStateData {
fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static
{
state.put(MiddlewareStateData { i: 10 });
chain(state)
}
}
Decorating the response after the request has completed:
#[derive(NewMiddleware, Copy, Clone)]
struct MiddlewareAddingResponseHeader;
impl Middleware for MiddlewareAddingResponseHeader {
fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static
{
chain(state)
.map_ok(|(state, mut response)| {
response.headers_mut().insert(WARNING, "299 example.com Deprecated".parse().unwrap());
(state, response)
})
.boxed()
}
}
Terminating the request early based on some arbitrary condition:
#[derive(NewMiddleware, Copy, Clone)]
struct ConditionalMiddleware;
impl Middleware for ConditionalMiddleware {
fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static
{
if *Method::borrow_from(&state) == Method::GET {
chain(state)
} else {
let response = create_empty_response(&state, StatusCode::METHOD_NOT_ALLOWED);
future::ok((state, response)).boxed()
}
}
}
Asynchronous middleware, which continues the request after some action completes:
#[derive(NewMiddleware, Copy, Clone)]
struct AsyncMiddleware;
impl Middleware for AsyncMiddleware {
fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static
{
// This could be any asynchronous action. `future::lazy(_)` defers a function
// until the next cycle of tokio's event loop.
let f = future::lazy(|_| Ok(()));
f.and_then(move |_| chain(state)).boxed()
}
}
Required methods
Entry point to the middleware. To pass the request on to the application, the middleware
invokes the chain
function with the provided state
.
By convention, the middleware should:
- Not modify any request components added to
State
by Gotham. - Avoid modifying parts of the
State
that don’t strictly need to be modified to perform its function.
Implementors
impl Middleware for CookieParser
Middleware
trait implementation.
impl Middleware for RequestLogger
Implementing gotham::middleware::Middleware
allows us to hook into the request chain
in order to correctly log out after a request has executed.
impl Middleware for SimpleLogger
Implementing gotham::middleware::Middleware
allows us to hook into the request chain
in order to correctly log out after a request has executed.
impl Middleware for SecurityMiddleware
Middleware
trait implementation.
impl Middleware for RequestTimer
Middleware
trait implementation.
impl<B, T> Middleware for SessionMiddleware<B, T> where
B: Backend + Send + 'static,
T: Default + Serialize + for<'de> Deserialize<'de> + Send + 'static,
impl<T> Middleware for StateMiddleware<T> where
T: Clone + RefUnwindSafe + StateData + Sync,
Middleware
trait implementation.