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
|
|
|
|
|
|
2017-08-11 22:29:42 +00:00
|
|
|
|
Any type that implements the [`Fairing`] trait is a _fairing_. Fairings hook
|
|
|
|
|
into Rocket's request lifecycle, receiving callbacks for events such as incoming
|
2017-09-28 03:17:40 +00:00
|
|
|
|
requests and outgoing responses. Rocket passes information about these events to
|
2018-10-22 21:47:35 +00:00
|
|
|
|
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
|
|
|
|
|
2017-08-11 22:29:42 +00:00
|
|
|
|
Rocket’s 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
|
2017-08-11 22:29:42 +00:00
|
|
|
|
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
|
|
|
|
|
2018-10-22 21:47:35 +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 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
|
2020-02-15 11:43:47 +00:00
|
|
|
|
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
|
2020-07-22 23:10:02 +00:00
|
|
|
|
# use rocket::launch;
|
|
|
|
|
#[launch]
|
2020-07-11 16:42:05 +00:00
|
|
|
|
fn rocket() -> rocket::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::ignite()
|
|
|
|
|
.attach(req_fairing)
|
|
|
|
|
.attach(res_fairing)
|
|
|
|
|
}
|
2017-07-07 03:46:43 +00:00
|
|
|
|
```
|
|
|
|
|
|
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
|
|
|
|
|
2017-07-11 11:43:08 +00:00
|
|
|
|
Fairings are executed in the order in which they are attached: the first
|
|
|
|
|
attached fairing has its callbacks executed before all others. Because fairing
|
|
|
|
|
callbacks may not be commutative, the order in which fairings are attached may
|
|
|
|
|
be significant.
|
|
|
|
|
|
2017-07-07 03:46:43 +00:00
|
|
|
|
### Callbacks
|
|
|
|
|
|
2017-07-11 11:43:08 +00:00
|
|
|
|
There are four events for which Rocket issues fairing callbacks. Each of these
|
|
|
|
|
events is described below:
|
2017-07-07 03:46:43 +00:00
|
|
|
|
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
* **Launch (`on_launch`)**
|
2017-07-07 03:46:43 +00:00
|
|
|
|
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
A launch callback is called just prior to liftoff while launching the
|
|
|
|
|
application. A launch callback can arbitrarily modify the `Rocket` instance
|
|
|
|
|
being constructed. They are are commonly 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
|
|
|
|
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
* **liftoff (`on_liftoff`)**
|
2017-07-07 03:46:43 +00:00
|
|
|
|
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +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
|
|
|
|
|
|
|
|
|
## 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
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
`Fairing` can implement any of the available callbacks: [`on_launch`],
|
|
|
|
|
[`on_liftoff`], [`on_request`], and [`on_response`]. Each callback has a default
|
2017-07-11 11:43:08 +00:00
|
|
|
|
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
|
|
|
|
|
[`on_launch`]: @api/rocket/fairing/trait.Fairing.html#method.on_launch
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
[`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
|
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
|
|
|
|
|
2017-07-07 03:50:39 +00:00
|
|
|
|
### Example
|
2017-07-07 03:46:43 +00:00
|
|
|
|
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +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
|
2020-02-15 11:43:47 +00:00
|
|
|
|
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.
|
2020-10-21 03:22:32 +00:00
|
|
|
|
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
|
2020-02-15 11:43:47 +00:00
|
|
|
|
};
|
2017-07-07 03:46:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-23 20:08:49 +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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2020-02-15 11:43:47 +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 simple occasions, implementing the `Fairing` trait can be cumbersome. This
|
|
|
|
|
is why Rocket provides the [`AdHoc`] type, which creates a fairing from a simple
|
2017-07-15 06:12:11 +00:00
|
|
|
|
function or closure. Using the `AdHoc` type is easy: simply call the
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
`on_launch`, `on_liftoff`, `on_request`, or `on_response` constructors on
|
|
|
|
|
`AdHoc` to create an `AdHoc` structure 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
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
ad-hoc fairings. The first, a liftoff fairing named "Liftoff Printer", simply
|
|
|
|
|
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::ignite()
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
|
.attach(AdHoc::on_liftoff("Liftoff Printer", |_| Box::pin(async move {
|
|
|
|
|
println!("...annnddd we have liftoff!");
|
|
|
|
|
})))
|
2020-01-08 16:03:05 +00:00
|
|
|
|
.attach(AdHoc::on_request("Put Rewriter", |req, _| Box::pin(async move {
|
2017-07-11 11:43:08 +00:00
|
|
|
|
req.set_method(Method::Put);
|
2020-01-08 16:03:05 +00:00
|
|
|
|
})));
|
2017-07-11 11:43:08 +00:00
|
|
|
|
```
|
|
|
|
|
|
2018-10-16 06:24:23 +00:00
|
|
|
|
[`AdHoc`]: @api/rocket/fairing/struct.AdHoc.html
|