[][src]Trait rocket::Handler

pub trait Handler: Cloneable + Send + Sync + 'static {
    fn handle<'r>(&self, request: &'r Request, data: Data) -> Outcome<'r>;
}

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:

  1. CustomHandler implements Clone. This is required so that CustomHandler implements Cloneable automatically. The Cloneable trait serves no other purpose but to ensure that every Handler can be cloned, allowing Routes to be cloned.
  2. CustomHandler implements Into<Vec<Route>>, allowing an instance to be used directly as the second parameter to rocket.mount().
  3. 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>

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.

Loading content...

Implementors

impl<F: Clone + Sync + Send + 'static> Handler for F where
    F: Fn(&'r Request, Data) -> Outcome<'r>, 
[src]

Loading content...