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
fn call<Chain>(
self,
state: State,
request: Request,
chain: Chain
) -> Box<HandlerFuture> where
Chain: FnOnce(State, Request) -> Box<HandlerFuture> + Send + 'static,
Self: Sized,
self,
state: State,
request: Request,
chain: Chain
) -> Box<HandlerFuture> where
Chain: FnOnce(State, Request) -> 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
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 callingchain
); - Ensure to pass the same
State
tochain
, rather than creating a newState
.
Implementors
impl<B, T> Middleware for SessionMiddleware<B, T> where
B: Backend + Send + 'static,
T: Default + Serialize + for<'de> Deserialize<'de> + Send + 'static,