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

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

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) -> Box<HandlerFuture>
        where Chain: FnOnce(State) -> 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) -> Box<HandlerFuture>
        where Chain: FnOnce(State) -> 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) -> Box<HandlerFuture>
        where Chain: FnOnce(State) -> Box<HandlerFuture> + Send + 'static
    {
        let f = chain(state)
            .map(|(state, mut response)| {
                response.headers_mut().insert(WARNING, "299 example.com Deprecated".parse().unwrap());
                (state, response)
            });

        Box::new(f)
    }
}

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) -> Box<HandlerFuture>
        where Chain: FnOnce(State) -> Box<HandlerFuture> + Send + 'static
    {
        if *Method::borrow_from(&state) == Method::GET {
            chain(state)
        } else {
            let response = create_empty_response(&state, StatusCode::METHOD_NOT_ALLOWED);
            Box::new(future::ok((state, response)))
        }
    }
}

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) -> Box<HandlerFuture>
        where Chain: FnOnce(State) -> 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(()));
        Box::new(f.and_then(move |_| chain(state)))
    }
}

Required methods

fn call<Chain>(self, state: State, chain: Chain) -> Box<HandlerFuture> where
    Chain: FnOnce(State) -> Box<HandlerFuture> + Send + 'static,
    Self: Sized

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.
Loading content...

Implementors

impl Middleware for CookieParser[src]

Middleware trait implementation.

fn call<Chain>(self, state: State, chain: Chain) -> Box<HandlerFuture> where
    Chain: FnOnce(State) -> Box<HandlerFuture>, 
[src]

Attaches a set of parsed cookies to the request state.

impl Middleware for RequestLogger[src]

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[src]

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[src]

Middleware trait implementation.

fn call<Chain>(self, state: State, chain: Chain) -> Box<HandlerFuture> where
    Chain: FnOnce(State) -> Box<HandlerFuture>, 
[src]

Attaches security headers to the response.

impl Middleware for RequestTimer[src]

Middleware trait implementation.

fn call<Chain>(self, state: State, chain: Chain) -> Box<HandlerFuture> where
    Chain: FnOnce(State) -> Box<HandlerFuture>, 
[src]

Attaches the request execution time to the response headers.

impl<B, T> Middleware for SessionMiddleware<B, T> where
    B: Backend + Send + 'static,
    T: Default + Serialize + for<'de> Deserialize<'de> + Send + 'static, 
[src]

impl<T> Middleware for StateMiddleware<T> where
    T: Clone + RefUnwindSafe + StateData + Sync
[src]

Middleware trait implementation.

fn call<Chain>(self, state: State, chain: Chain) -> Box<HandlerFuture> where
    Chain: FnOnce(State) -> Box<HandlerFuture>, 
[src]

Attaches the inner generic value to the request state.

This will enable the Handler to borrow the value directly from the state.

Loading content...