Trait rocket::fairing::Fairing [] [src]

pub trait Fairing: Send + Sync + 'static {
    fn info(&self) -> Info;

    fn on_attach(&self, rocket: Rocket) -> Result<Rocket, Rocket> { ... }
fn on_launch(&self, rocket: &Rocket) { ... }
fn on_request(&self, request: &mut Request, data: &Data) { ... }
fn on_response(&self, request: &Request, response: &mut Response) { ... } }

Trait implemented by fairings: Rocket's structured middleware.

Considerations

Fairings are a large hammer that can easily be abused and misused. If you are considering writing a Fairing implementation, first consider if it is appropriate to do so. While middleware is often the best solution to some problems in other frameworks, it is often a suboptimal solution in Rocket. This is because Rocket provides richer mechanisms such as request guards and data guards that can be used to accomplish the same objective in a cleaner, more composable, and more robust manner.

As a general rule of thumb, only globally applicable actions should be implemented via fairings. For instance, you should not use a fairing to implement authentication or authorization (preferring to use a request guard instead) unless the authentication or authorization applies to the entire application. On the other hand, you should use a fairing to record timing and/or usage statistics or to implement global security policies.

Fairing Callbacks

There are four kinds of fairing callbacks: attach, launch, request, and response. A fairing can request any combination of these callbacks through the kind field of the Info structure returned from the info method. Rocket will only invoke the callbacks set in the kind field.

The four callback kinds are as follows:

Implementing

A Fairing implementation has one required method: info. A Fairing can also implement any of the available callbacks: on_attach, on_launch, on_request, and on_response. A Fairing must set the appropriate callback kind in the kind field of the returned Info structure from info for a callback to actually be called by Rocket.

Fairing Info

Every Fairing must implement the info method, which returns an Info structure. This structure is used by Rocket to:

  1. Assign a name to the Fairing.

    This is the name field, which can be any arbitrary string. Name your fairing something illustrative. The name will be logged during the application's launch procedures.

  2. Determine which callbacks to actually issue on the Fairing.

    This is the kind field of type Kind. This field is a bitset that represents the kinds of callbacks the fairing wishes to receive. Rocket will only invoke the callbacks that are flagged in this set. Kind structures can be ord together to represent any combination of kinds of callbacks. For instance, to request launch and response callbacks, return a kind field with the value Kind::Launch | Kind::Response.

Restrictions

A Fairing must be Send + Sync + 'static. This means that the fairing must be sendable across thread boundaries (Send), thread-safe (Sync), and have only 'static references, if any ('static). Note that these bounds do not prohibit a Fairing from holding state: the state need simply be thread-safe and statically available or heap allocated.

Example

Imagine that we want to record the number of GET and POST requests that our application has received. While we could do this with request guards and managed state, it would require us to annotate every GET and POST request with custom types, polluting handler signatures. Instead, we can create a simple fairing that acts globally.

The Counter fairing below records the number of all GET and POST requests received. It makes these counts available at a special '/counts' path.

use std::io::Cursor;
use std::sync::atomic::{AtomicUsize, Ordering};

use rocket::{Request, Data, Response};
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::{Method, ContentType, Status};

#[derive(Default)]
struct Counter {
    get: AtomicUsize,
    post: AtomicUsize,
}

impl Fairing for Counter {
    fn info(&self) -> Info {
        Info {
            name: "GET/POST Counter",
            kind: Kind::Request | Kind::Response
        }
    }

    fn on_request(&self, request: &mut Request, _: &Data) {
        if request.method() == Method::Get {
            self.get.fetch_add(1, Ordering::Relaxed);
        } else if request.method() == Method::Post {
            self.post.fetch_add(1, Ordering::Relaxed);
        }
    }

    fn on_response(&self, request: &Request, response: &mut Response) {
        // Don't change a successful user's response, ever.
        if response.status() != Status::NotFound {
            return
        }

        if request.method() == Method::Get && request.uri().path() == "/counts" {
            let get_count = self.get.load(Ordering::Relaxed);
            let post_count = self.post.load(Ordering::Relaxed);

            let body = format!("Get: {}\nPost: {}", get_count, post_count);
            response.set_status(Status::Ok);
            response.set_header(ContentType::Plain);
            response.set_sized_body(Cursor::new(body));
        }
    }
}

Required Methods

Returns an Info structure containing the name and Kind of this fairing. The name can be any arbitrary string. Kind must be an ord set of Kind variants.

This is the only required method of a Fairing. All other methods have no-op default implementations.

Rocket will only dispatch callbacks to this fairing for the kinds in the kind field of the returned Info structure. For instance, if Kind::Launch | Kind::Request is used, then Rocket will only call the on_launch and on_request methods of the fairing. Similarly, if Kind::Response is used, Rocket will only call the on_response method of this fairing.

Example

An info implementation for MyFairing: a fairing named "My Custom Fairing" that is both a launch and response fairing.

use rocket::fairing::{Fairing, Info, Kind};

struct MyFairing;

impl Fairing for MyFairing {
    fn info(&self) -> Info {
        Info {
            name: "My Custom Fairing",
            kind: Kind::Launch | Kind::Response
        }
    }
}

Provided Methods

The attach callback. Returns Ok if launch should proceed and Err if launch should be aborted.

This method is called when a fairing is attached if Kind::Attach is in the kind field of the Info structure for this fairing. The rocket parameter is the Rocket instance that is currently being built for this application.

Default Implementation

The default implementation of this method simply returns Ok(rocket).

The launch callback.

This method is called just prior to launching the application if Kind::Launch is in the kind field of the Info structure for this fairing. The &Rocket parameter curresponds to the application that will be launched.

Default Implementation

The default implementation of this method does nothing.

The request callback.

This method is called when a new request is received if Kind::Request is in the kind field of the Info structure for this fairing. The &mut Request parameter is the incoming request, and the &Data parameter is the incoming data in the request.

Default Implementation

The default implementation of this method does nothing.

The response callback.

This method is called when a response is ready to be issued to a client if Kind::Response is in the kind field of the Info structure for this fairing. The &Request parameter is the request that was routed, and the &mut Response parameter is the resulting response.

Default Implementation

The default implementation of this method does nothing.

Implementations on Foreign Types

impl<T: Fairing> Fairing for Arc<T>
[src]

[src]

[src]

[src]

[src]

[src]

Implementors