Trait rocket::Handler [−][src]
Trait implemented by types that can handle requests.
In general, you will never need to implement Handler
manually or be
concerned about the Handler
trait; Rocket's code generation handles
everything for you. You only need to learn about this trait if you want to
provide an external, library-based mechanism to handle requests where
request handling depends on input from the user. In other words, if you want
to write a plugin for Rocket that looks mostly like a static route but need
user provided state to make a request handling decision, you should consider
implementing a custom Handler
.
Example
Say you'd like to write a handler that changes its functionality based on an enum value that the user provides:
#[derive(Copy, Clone)] enum Kind { Simple, Intermediate, Complex, }
Such a handler might be written and used as follows:
use rocket::{Request, Data, Route, http::Method}; use rocket::handler::{self, Handler, Outcome}; #[derive(Clone)] struct CustomHandler(Kind); impl Handler for CustomHandler { fn handle<'r>(&self, req: &'r Request, data: Data) -> Outcome<'r> { match self.0 { Kind::Simple => Outcome::from(req, "simple"), Kind::Intermediate => Outcome::from(req, "intermediate"), Kind::Complex => Outcome::from(req, "complex"), } } } impl Into<Vec<Route>> for CustomHandler { fn into(self) -> Vec<Route> { vec![Route::new(Method::Get, "/", self)] } } fn main() { rocket::ignite() .mount("/", CustomHandler(Kind::Simple)) .launch(); }
Note the following:
CustomHandler
implementsClone
. This is required so thatCustomHandler
implementsCloneable
automatically. TheCloneable
trait serves no other purpose but to ensure that everyHandler
can be cloned, allowingRoute
s to be cloned.CustomHandler
implementsInto<Vec<Route>>
, allowing an instance to be used directly as the second parameter torocket.mount()
.- Unlike static-function-based handlers, this custom handler can make use of any internal state.
Alternatives
The previous example could have been implemented using a combination of managed state and a static route, as follows:
use rocket::State; #[get("/")] fn custom_handler(state: State<Kind>) -> &'static str { match *state { Kind::Simple => "simple", Kind::Intermediate => "intermediate", Kind::Complex => "complex", } } fn main() { rocket::ignite() .mount("/", routes![custom_handler]) .manage(Kind::Simple) .launch(); }
Pros:
- The handler is easier to implement since Rocket's code generation ensures type-safety at all levels.
Cons:
- Only one
Kind
can be stored in managed state. As such, only one variant of the custom handler can be used. - The user must remember to manually call
rocket.manage(state)
.
Use this alternative when a single configuration is desired and your custom
handler is private to your application. For all other cases, a custom
Handler
implementation is preferred.
Required methods
fn handle<'r>(&self, request: &'r Request<'_>, data: Data) -> Outcome<'r>
[src]
Called by Rocket when a Request
with its associated Data
should be
handled by this handler.
The variant of Outcome
returned determines what Rocket does next. If
the return value is a Success(Response)
, the wrapped Response
is
used to respond to the client. If the return value is a
Failure(Status)
, the error catcher for Status
is invoked to generate
a response. Otherwise, if the return value is Forward(Data)
, the next
matching route is attempted. If there are no other matching routes, the
404
error catcher is invoked.
Implementors
impl<F: Clone + Sync + Send + 'static> Handler for F where
F: Fn(&'r Request<'_>, Data) -> Outcome<'r>,
[src]
F: Fn(&'r Request<'_>, Data) -> Outcome<'r>,