Rocket/site/guide/7-fairings.md

245 lines
10 KiB
Markdown
Raw Normal View History

2017-07-07 03:46:43 +00:00
# Fairings
2017-07-11 11:43:08 +00:00
Fairings are Rocket's approach to structured middleware. With fairings, your
application can hook into the request lifecycle to record or rewrite information
about incoming requests and outgoing responses.
2017-07-07 03:46:43 +00:00
## Overview
Any type that implements the [`Fairing`] trait is a _fairing_. Fairings hook
into Rocket's request lifecycle, receiving callbacks for events such as incoming
requests and outgoing responses. Rocket passes information about these events to
the fairing; the fairing can do what it wants with the information. This
includes rewriting requests or responses, recording information about the event,
or doing nothing at all.
2017-07-11 11:43:08 +00:00
Rockets fairings are a lot like middleware from other frameworks, but they bear
a few key distinctions:
2017-07-11 11:43:08 +00:00
* Fairings **cannot** terminate or respond to an incoming request directly.
* Fairings **cannot** inject arbitrary, non-request data into a request.
* Fairings _can_ prevent an application from launching.
* Fairings _can_ inspect and modify the application's configuration.
If you are familiar with middleware from other frameworks, you may find yourself
reaching for fairings instinctively. Before doing so, remember that Rocket
provides a rich set of mechanisms such as [request guards] and [data guards]
that can be used to solve problems in a clean, composable, and robust manner.
2017-07-11 11:43:08 +00:00
! warning
As a general rule of thumb, only _globally applicable_ actions should be
effected through fairings. 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 all or the
overwhelming majority of the application. On the other hand, you _should_ use a
fairing to record timing and usage statistics or to enforce global security
policies.
2017-07-07 03:46:43 +00:00
2018-10-16 05:50:35 +00:00
[`Fairing`]: @api/rocket/fairing/trait.Fairing.html
[request guard]: ../requests/#request-guards
[request guards]: ../requests/#request-guards
[data guards]: ../requests/#body-data
2017-07-07 03:46:43 +00:00
### Attaching
2017-07-11 11:43:08 +00:00
Fairings are registered with Rocket via the [`attach`] method on a [`Rocket`]
instance. Only when a fairing is attached will its callbacks fire. As an
example, the following snippet attached two fairings, `req_fairing` and
2017-07-11 11:43:08 +00:00
`res_fairing`, to a new Rocket instance:
2017-07-07 03:46:43 +00:00
```rust
# use rocket::launch;
#[launch]
fn rocket() -> _ {
# let req_fairing = rocket::fairing::AdHoc::on_request("example", |_, _| Box::pin(async {}));
# let res_fairing = rocket::fairing::AdHoc::on_response("example", |_, _| Box::pin(async {}));
rocket::build()
.attach(req_fairing)
.attach(res_fairing)
}
2017-07-07 03:46:43 +00:00
```
Fairings are executed in the order in which they are attached: the first
attached fairing has its callbacks executed before all others. A fairing can be
attached any number of times. Except for [singleton fairings], all attached
instances are polled at runtime. Fairing callbacks may not be commutative; the
order in which fairings are attached may be significant.
[singleton fairings]: @api/rocket/fairing/trait.Fairing.html#singletons
2018-10-16 05:50:35 +00:00
[`attach`]: @api/rocket/struct.Rocket.html#method.attach
[`Rocket`]: @api/rocket/struct.Rocket.html
2017-07-07 03:46:43 +00:00
### Callbacks
There are five events for which Rocket issues fairing callbacks. Each of these
events is briefly described below and in details in the [`Fairing`] trait docs:
2017-07-07 03:46:43 +00:00
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
* **Ignite (`on_ignite`)**
2017-07-07 03:46:43 +00:00
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
An ignite callback is called during [ignition] An ignite callback can
arbitrarily modify the `Rocket` instance being built. They are commonly
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
used to parse and validate configuration values, aborting on bad
configurations, and inserting the parsed value into managed state for later
retrieval.
2017-07-07 03:46:43 +00:00
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
* **Liftoff (`on_liftoff`)**
2017-07-07 03:46:43 +00:00
A liftoff callback is called immediately after a Rocket application has
launched. A liftoff callback can inspect the `Rocket` instance being
launched. A liftoff callback can be a convenient hook for launching services
2017-07-11 11:43:08 +00:00
related to the Rocket application being launched.
2017-07-07 03:46:43 +00:00
2017-07-11 11:43:08 +00:00
* **Request (`on_request`)**
2017-07-07 03:46:43 +00:00
A request callback is called just after a request is received. A request
callback can modify the request at will and peek into the incoming data. It
may not, however, abort or respond directly to the request; these issues are
better handled via request guards or via response callbacks.
2017-07-11 11:43:08 +00:00
* **Response (`on_response`)**
2017-07-07 03:46:43 +00:00
A response callback is called when a response is ready to be sent to the
2017-07-11 11:43:08 +00:00
client. A response callback can modify part or all of the response. As such,
a response fairing can be used to provide a response when the greater
2018-08-09 02:06:52 +00:00
application fails by rewriting **404** responses as desired. As another
2017-07-11 11:43:08 +00:00
example, response fairings can also be used to inject headers into all
outgoing responses.
2017-07-07 03:46:43 +00:00
* **Shutdown (`on_shutdown`)**
A shutdown callback is called when [shutdown is triggered]. At this point,
graceful shutdown has commenced but not completed; no new requests are
accepted but the application may still be actively serving existing
requests. All registered shutdown fairings are run concurrently; resolution
of all fairings is awaited before resuming shutdown.
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
[ignition]: @api/rocket/struct.Rocket.html#method.ignite
[shutdown is triggered]: @api/rocket/config/struct.Shutdown.html#triggers
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
2017-07-07 03:46:43 +00:00
## Implementing
2017-07-11 11:43:08 +00:00
Recall that a fairing is any type that implements the [`Fairing`] trait. A
`Fairing` implementation has one required method: [`info`], which returns an
[`Info`] structure. This structure is used by Rocket to assign a name to the
fairing and determine the set of callbacks the fairing is registering for. A
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
`Fairing` can implement any of the available callbacks: [`on_ignite`],
[`on_liftoff`], [`on_request`], [`on_response`], and [`on_shutdown`]. Each
callback has a default implementation that does absolutely nothing.
2017-07-07 03:46:43 +00:00
2018-10-16 05:50:35 +00:00
[`Info`]: @api/rocket/fairing/struct.Info.html
[`info`]: @api/rocket/fairing/trait.Fairing.html#tymethod.info
Introduce statically-enforced 'Rocket' phasing. The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where 'Phase' is a newly introduced, sealed marker trait. The trait is implemented by three new marker types representing the three launch phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three phases, in order, is enforced, as are the invariants guaranteed by each phase. In particular, an instance of 'Rocket' is guaranteed to be in its final configuration after the 'Build' phase and represent a running local or public server in the 'Orbit' phase. The 'Ignite' phase serves as an intermediate, enabling inspection of a finalized but stationary instance. Transition between phases validates the invariants required by the transition. All APIs have been adjusted appropriately, requiring either an instance of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or 'Rocket<Orbit>') or operating generically on a 'Rocket<P>'. Documentation is also updated and substantially improved to mention required and guaranteed invariants. Additionally, this commit makes the following relevant changes: * 'Rocket::ignite()' is now a public interface. * 'Rocket::{build,custom}' methods can no longer panic. * 'Launch' fairings are now 'ignite' fairings. * 'Liftoff' fairings are always run, even in local mode. * All 'ignite' fairings run concurrently at ignition. * Launch logging occurs on launch, not any point prior. * Launch log messages have improved formatting. * A new launch error kind, 'Config', was added. * A 'fairing::Result' type alias was introduced. * 'Shutdown::shutdown()' is now 'Shutdown::notify()'. Some internal changes were also introduced: * Fairing 'Info' name for 'Templates' is now 'Templating'. * Shutdown is implemented using 'tokio::sync::Notify'. * 'Client::debug()' is used nearly universally in tests. Resolves #1154. Resolves #1136.
2021-04-14 02:26:45 +00:00
[`on_ignite`]: @api/rocket/fairing/trait.Fairing.html#method.on_ignite
[`on_liftoff`]: @api/rocket/fairing/trait.Fairing.html#method.on_liftoff
2018-10-16 05:50:35 +00:00
[`on_request`]: @api/rocket/fairing/trait.Fairing.html#method.on_request
[`on_response`]: @api/rocket/fairing/trait.Fairing.html#method.on_response
[`on_shutdown`]: @api/rocket/fairing/trait.Fairing.html#method.on_shutdown
2017-07-07 03:46:43 +00:00
2017-07-11 11:43:08 +00:00
### Requirements
2017-07-07 03:46:43 +00:00
2017-07-11 11:43:08 +00:00
A type implementing `Fairing` is required to 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.
2017-07-07 03:46:43 +00:00
### Example
2017-07-07 03:46:43 +00:00
As an example, 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
2017-07-07 03:46:43 +00:00
fairing that acts globally.
2017-07-11 11:43:08 +00:00
The code for a `Counter` fairing below implements exactly this. The fairing
receives a request callback, where it increments a counter on each `GET` and
`POST` request. It also receives a response callback, where it responds to
unrouted requests to the `/counts` path by returning the recorded number of
counts.
2017-07-07 03:46:43 +00:00
```rust
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};
2017-07-07 03:46:43 +00:00
struct Counter {
get: AtomicUsize,
post: AtomicUsize,
}
2020-07-11 16:41:53 +00:00
#[rocket::async_trait]
2017-07-07 03:46:43 +00:00
impl Fairing for Counter {
2017-07-12 22:36:16 +00:00
// This is a request and response fairing named "GET/POST Counter".
2017-07-07 03:46:43 +00:00
fn info(&self) -> Info {
Info {
name: "GET/POST Counter",
kind: Kind::Request | Kind::Response
}
}
2017-07-11 11:43:08 +00:00
// Increment the counter for `GET` and `POST` requests.
async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {
2017-07-07 03:46:43 +00:00
match request.method() {
Method::Get => self.get.fetch_add(1, Ordering::Relaxed),
Method::Post => self.post.fetch_add(1, Ordering::Relaxed),
_ => return
};
2017-07-07 03:46:43 +00:00
}
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
2020-07-11 16:41:53 +00:00
// Don't change a successful user's response, ever.
if response.status() != Status::NotFound {
return
}
// Rewrite the response to return the current counts.
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(body.len(), Cursor::new(body));
}
2017-07-07 03:46:43 +00:00
}
}
```
The complete example can be found in the [`Fairing`
documentation](@api/rocket/fairing/trait.Fairing.html#example).
2017-07-11 11:43:08 +00:00
## Ad-Hoc Fairings
For simpler cases, implementing the `Fairing` trait can be cumbersome. This is
why Rocket provides the [`AdHoc`] type, which creates a fairing from a simple
function or closure. Using the `AdHoc` type is easy: simply call the
`on_ignite`, `on_liftoff`, `on_request`, `on_response`, or `on_shutdown`
constructors on `AdHoc` to create a fairing from a function or closure.
2017-07-11 11:43:08 +00:00
As an example, the code below creates a `Rocket` instance with two attached
ad-hoc fairings. The first, a liftoff fairing named "Liftoff Printer", prints a
message indicating that the application has launched. The second named "Put
Rewriter", a request fairing, rewrites the method of all requests to be `PUT`.
2017-07-11 11:43:08 +00:00
```rust
use rocket::fairing::AdHoc;
use rocket::http::Method;
rocket::build()
.attach(AdHoc::on_liftoff("Liftoff Printer", |_| Box::pin(async move {
println!("...annnddd we have liftoff!");
})))
.attach(AdHoc::on_request("Put Rewriter", |req, _| Box::pin(async move {
2017-07-11 11:43:08 +00:00
req.set_method(Method::Put);
})))
.attach(AdHoc::on_shutdown("Shutdown Printer", |_| Box::pin(async move {
println!("...shutdown has commenced!");
})));
2017-07-11 11:43:08 +00:00
```
2018-10-16 06:24:23 +00:00
[`AdHoc`]: @api/rocket/fairing/struct.AdHoc.html