Trait gotham::middleware::Middleware [] [src]

pub trait Middleware {
    fn call<Chain>(
        self,
        state: State,
        request: Request,
        chain: Chain
    ) -> Box<HandlerFuture>
    where
        Chain: FnOnce(State, Request) -> Box<HandlerFuture> + Send + 'static,
        Self: Sized
; }

Middleware has the opportunity to provide additional behaviour to the Request / Response interaction. Middleware-specific state data can be recorded in the State struct for use elsewhere.

Examples

Taking no action, and immediately passing the Request through to the rest of the application:

struct NoopMiddleware;

impl Middleware for NoopMiddleware {
    fn call<Chain>(self, state: State, req: Request, chain: Chain) -> Box<HandlerFuture>
        where Chain: FnOnce(State, Request) -> Box<HandlerFuture> + Send + 'static
    {
        chain(state, req)
    }
}

Recording a piece of state data before passing the request through:

struct MiddlewareWithStateData;

struct MiddlewareStateData {
    i: i32,
}

impl Middleware for MiddlewareWithStateData {
    fn call<Chain>(self, mut state: State, req: Request, chain: Chain) -> Box<HandlerFuture>
        where Chain: FnOnce(State, Request) -> Box<HandlerFuture> + Send + 'static
    {
        state.put(MiddlewareStateData { i: 10 });
        chain(state, req)
    }
}

Terminating the request early based on some arbitrary condition:

struct ConditionalMiddleware;

impl Middleware for ConditionalMiddleware {
    fn call<Chain>(self, state: State, req: Request, chain: Chain) -> Box<HandlerFuture>
        where Chain: FnOnce(State, Request) -> Box<HandlerFuture> + Send + 'static
    {
        if *req.method() == Method::Get {
            chain(state, req)
        } else {
            let response = create_response(&state, StatusCode::MethodNotAllowed, None);
            future::ok((state, response)).boxed()
        }
    }
}

Asynchronous middleware, which continues the request after some action completes:

struct AsyncMiddleware;

impl Middleware for AsyncMiddleware {
    fn call<Chain>(self, state: State, req: Request, chain: Chain) -> Box<HandlerFuture>
        where Chain: FnOnce(State, Request) -> 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(|| future::ok(()));
        f.and_then(move |_| chain(state, req)).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 and request.

By convention, the middleware should:

  • Avoid modifying the Request, unless it is already determined that the response will be generated by the middleware (i.e. without calling chain);
  • Ensure to pass the same State to chain, rather than creating a new State.

Implementors