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§

Middleware trait implementation.

Implementing gotham::middleware::Middleware allows us to hook into the request chain in order to correctly log out after a request has executed.

Implementing gotham::middleware::Middleware allows us to hook into the request chain in order to correctly log out after a request has executed.

Middleware trait implementation.

Middleware trait implementation.

Middleware trait implementation.