Require all 'AdHoc' fairings to be named.

This commit is contained in:
Sergio Benitez 2018-08-14 09:14:06 -07:00
parent 589743579a
commit e0961e0750
10 changed files with 70 additions and 85 deletions

View File

@ -185,7 +185,7 @@
//!
//! fn main() {
//! rocket::ignite()
//! .attach(AdHoc::on_attach(|rocket| {
//! .attach(AdHoc::on_attach("Token Config", |rocket| {
//! println!("Adding token managed state from config...");
//! let token_val = rocket.config().get_int("token").unwrap_or(-1);
//! Ok(rocket.manage(Token(token_val)))

View File

@ -19,41 +19,43 @@ use fairing::{Fairing, Kind, Info};
/// # Example
///
/// The following snippet creates a `Rocket` instance with two ad-hoc fairings.
/// The first, a launch fairing, simply prints a message indicating that the
/// application is about to the launch. The second, a request fairing, rewrites
/// the method of all requests to be `PUT`.
/// The first, a launch fairing named "Launch Printer", simply prints a message
/// indicating that the application is about to the launch. The second named
/// "Put Rewriter", a request fairing, rewrites the method of all requests to be
/// `PUT`.
///
/// ```rust
/// use rocket::fairing::AdHoc;
/// use rocket::http::Method;
///
/// rocket::ignite()
/// .attach(AdHoc::on_launch(|_| {
/// .attach(AdHoc::on_launch("Launch Printer", |_| {
/// println!("Rocket is about to launch! Exciting! Here we go...");
/// }))
/// .attach(AdHoc::on_request(|req, _| {
/// .attach(AdHoc::on_request("Put Rewriter", |req, _| {
/// req.set_method(Method::Put);
/// }));
/// ```
pub enum AdHoc {
pub struct AdHoc {
name: &'static str,
kind: AdHocKind,
}
enum AdHocKind {
/// An ad-hoc **attach** fairing. Called when the fairing is attached.
#[doc(hidden)]
Attach(Mutex<Option<Box<FnBox(Rocket) -> Result<Rocket, Rocket> + Send + 'static>>>),
/// An ad-hoc **launch** fairing. Called just before Rocket launches.
#[doc(hidden)]
Launch(Mutex<Option<Box<FnBox(&Rocket) + Send + 'static>>>),
/// An ad-hoc **request** fairing. Called when a request is received.
#[doc(hidden)]
Request(Box<Fn(&mut Request, &Data) + Send + Sync + 'static>),
/// An ad-hoc **response** fairing. Called when a response is ready to be
/// sent to a client.
#[doc(hidden)]
Response(Box<Fn(&Request, &mut Response) + Send + Sync + 'static>),
}
impl AdHoc {
/// Constructs an `AdHoc` attach fairing. The function `f` will be called by
/// Rocket when this fairing is attached.
/// Constructs an `AdHoc` attach fairing named `name`. The function `f` will
/// be called by Rocket when this fairing is attached.
///
/// # Example
///
@ -61,16 +63,16 @@ impl AdHoc {
/// use rocket::fairing::AdHoc;
///
/// // The no-op attach fairing.
/// let fairing = AdHoc::on_attach(|rocket| Ok(rocket));
/// let fairing = AdHoc::on_attach("No-Op", |rocket| Ok(rocket));
/// ```
pub fn on_attach<F>(f: F) -> AdHoc
pub fn on_attach<F>(name: &'static str, f: F) -> AdHoc
where F: FnOnce(Rocket) -> Result<Rocket, Rocket> + Send + 'static
{
AdHoc::Attach(Mutex::new(Some(Box::new(f))))
AdHoc { name, kind: AdHocKind::Attach(Mutex::new(Some(Box::new(f)))) }
}
/// Constructs an `AdHoc` launch fairing. The function `f` will be called by
/// Rocket just prior to launching.
/// Constructs an `AdHoc` launch fairing named `name`. The function `f` will
/// be called by Rocket just prior to launching.
///
/// # Example
///
@ -78,18 +80,18 @@ impl AdHoc {
/// use rocket::fairing::AdHoc;
///
/// // A fairing that prints a message just before launching.
/// let fairing = AdHoc::on_launch(|rocket| {
/// let fairing = AdHoc::on_launch("Launch Count", |rocket| {
/// println!("Launching in T-3..2..1..");
/// });
/// ```
pub fn on_launch<F>(f: F) -> AdHoc
pub fn on_launch<F>(name: &'static str, f: F) -> AdHoc
where F: FnOnce(&Rocket) + Send + 'static
{
AdHoc::Launch(Mutex::new(Some(Box::new(f))))
AdHoc { name, kind: AdHocKind::Launch(Mutex::new(Some(Box::new(f)))) }
}
/// Constructs an `AdHoc` request fairing. The function `f` will be called
/// by Rocket when a new request is received.
/// Constructs an `AdHoc` request fairing named `name`. The function `f`
/// will be called by Rocket when a new request is received.
///
/// # Example
///
@ -97,19 +99,19 @@ impl AdHoc {
/// use rocket::fairing::AdHoc;
///
/// // The no-op request fairing.
/// let fairing = AdHoc::on_request(|req, data| {
/// let fairing = AdHoc::on_request("Dummy", |req, data| {
/// // do something with the request and data...
/// # let (_, _) = (req, data);
/// });
/// ```
pub fn on_request<F>(f: F) -> AdHoc
pub fn on_request<F>(name: &'static str, f: F) -> AdHoc
where F: Fn(&mut Request, &Data) + Send + Sync + 'static
{
AdHoc::Request(Box::new(f))
AdHoc { name, kind: AdHocKind::Request(Box::new(f)) }
}
/// Constructs an `AdHoc` response fairing. The function `f` will be called
/// by Rocket when a response is ready to be sent.
/// Constructs an `AdHoc` response fairing named `name`. The function `f`
/// will be called by Rocket when a response is ready to be sent.
///
/// # Example
///
@ -117,51 +119,32 @@ impl AdHoc {
/// use rocket::fairing::AdHoc;
///
/// // The no-op response fairing.
/// let fairing = AdHoc::on_response(|req, resp| {
/// let fairing = AdHoc::on_response("Dummy", |req, resp| {
/// // do something with the request and pending response...
/// # let (_, _) = (req, resp);
/// });
/// ```
pub fn on_response<F>(f: F) -> AdHoc
pub fn on_response<F>(name: &'static str, f: F) -> AdHoc
where F: Fn(&Request, &mut Response) + Send + Sync + 'static
{
AdHoc::Response(Box::new(f))
AdHoc { name, kind: AdHocKind::Response(Box::new(f)) }
}
}
impl Fairing for AdHoc {
fn info(&self) -> Info {
use self::AdHoc::*;
match *self {
Attach(_) => {
Info {
name: "AdHoc::Attach",
kind: Kind::Attach,
}
}
Launch(_) => {
Info {
name: "AdHoc::Launch",
kind: Kind::Launch,
}
}
Request(_) => {
Info {
name: "AdHoc::Request",
kind: Kind::Request,
}
}
Response(_) => {
Info {
name: "AdHoc::Response",
kind: Kind::Response,
}
}
}
let kind = match self.kind {
AdHocKind::Attach(_) => Kind::Attach,
AdHocKind::Launch(_) => Kind::Launch,
AdHocKind::Request(_) => Kind::Request,
AdHocKind::Response(_) => Kind::Response,
};
Info { name: self.name, kind }
}
fn on_attach(&self, rocket: Rocket) -> Result<Rocket, Rocket> {
if let AdHoc::Attach(ref mutex) = *self {
if let AdHocKind::Attach(ref mutex) = self.kind {
let mut option = mutex.lock().expect("AdHoc::Attach lock");
option.take()
.expect("internal error: `on_attach` single-call invariant broken")
@ -172,7 +155,7 @@ impl Fairing for AdHoc {
}
fn on_launch(&self, rocket: &Rocket) {
if let AdHoc::Launch(ref mutex) = *self {
if let AdHocKind::Launch(ref mutex) = self.kind {
let mut option = mutex.lock().expect("AdHoc::Launch lock");
option.take()
.expect("internal error: `on_launch` single-call invariant broken")
@ -181,13 +164,13 @@ impl Fairing for AdHoc {
}
fn on_request(&self, request: &mut Request, data: &Data) {
if let AdHoc::Request(ref callback) = *self {
if let AdHocKind::Request(ref callback) = self.kind {
callback(request, data)
}
}
fn on_response(&self, request: &Request, response: &mut Response) {
if let AdHoc::Response(ref callback) = *self {
if let AdHocKind::Response(ref callback) = self.kind {
callback(request, response)
}
}

View File

@ -23,8 +23,8 @@
//!
//! ```rust
//! # use rocket::fairing::AdHoc;
//! # let req_fairing = AdHoc::on_request(|_, _| ());
//! # let res_fairing = AdHoc::on_response(|_, _| ());
//! # let req_fairing = AdHoc::on_request("Request", |_, _| ());
//! # let res_fairing = AdHoc::on_response("Response", |_, _| ());
//! let rocket = rocket::ignite()
//! .attach(req_fairing)
//! .attach(res_fairing);

View File

@ -649,7 +649,9 @@ impl Rocket {
/// fn main() {
/// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite()
/// .attach(AdHoc::on_launch(|_| println!("Rocket is launching!")))
/// .attach(AdHoc::on_launch("Launch Message", |_| {
/// println!("Rocket is launching!");
/// }))
/// .launch();
/// # }
/// }
@ -821,7 +823,7 @@ impl Rocket {
/// fn main() {
/// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite()
/// .attach(AdHoc::on_launch(|rocket| {
/// .attach(AdHoc::on_launch("Config Printer", |rocket| {
/// println!("Rocket launch config: {:?}", rocket.config());
/// }))
/// .launch();

View File

@ -31,10 +31,10 @@ mod fairing_before_head_strip {
fn not_auto_handled() {
let rocket = rocket::ignite()
.mount("/", routes![head])
.attach(AdHoc::on_request(|req, _| {
.attach(AdHoc::on_request("Check HEAD", |req, _| {
assert_eq!(req.method(), Method::Head);
}))
.attach(AdHoc::on_response(|req, res| {
.attach(AdHoc::on_response("Check HEAD 2", |req, res| {
assert_eq!(req.method(), Method::Head);
assert_eq!(res.body_string(), Some(RESPONSE_STRING.into()));
}));
@ -54,14 +54,14 @@ mod fairing_before_head_strip {
let rocket = rocket::ignite()
.mount("/", routes![auto])
.manage(counter)
.attach(AdHoc::on_request(|req, _| {
.attach(AdHoc::on_request("Check HEAD + Count", |req, _| {
assert_eq!(req.method(), Method::Head);
// This should be called exactly once.
let c = req.guard::<State<Counter>>().unwrap();
assert_eq!(c.0.fetch_add(1, Ordering::SeqCst), 0);
}))
.attach(AdHoc::on_response(|req, res| {
.attach(AdHoc::on_response("Check GET", |req, res| {
assert_eq!(req.method(), Method::Get);
assert_eq!(res.body_string(), Some(RESPONSE_STRING.into()));
}));

View File

@ -25,11 +25,11 @@ fn index(counter: State<Counter>) -> String {
fn rocket() -> rocket::Rocket {
rocket::ignite()
.mount("/", routes![index])
.attach(AdHoc::on_attach(|rocket| {
.attach(AdHoc::on_attach("Outer", |rocket| {
let counter = Counter::default();
counter.attach.fetch_add(1, Ordering::Relaxed);
let rocket = rocket.manage(counter)
.attach(AdHoc::on_request(|req, _| {
.attach(AdHoc::on_request("Inner", |req, _| {
if req.method() == Method::Get {
let counter = req.guard::<State<Counter>>().unwrap();
counter.get.fetch_add(1, Ordering::Release);

View File

@ -55,7 +55,7 @@ pub fn test_config(environment: Environment) {
::std::env::set_var("ROCKET_ENV", environment.to_string());
let rocket = rocket::ignite()
.attach(AdHoc::on_attach(|rocket| {
.attach(AdHoc::on_attach("Local Config", |rocket| {
println!("Attaching local config.");
let config = rocket.config().clone();
Ok(rocket.manage(LocalConfig(config)))

View File

@ -67,22 +67,22 @@ fn rocket() -> rocket::Rocket {
rocket::ignite()
.mount("/", routes![hello, token])
.attach(Counter::default())
.attach(AdHoc::on_attach(|rocket| {
.attach(AdHoc::on_attach("Token State", |rocket| {
println!("Adding token managed state...");
let token_val = rocket.config().get_int("token").unwrap_or(-1);
Ok(rocket.manage(Token(token_val)))
}))
.attach(AdHoc::on_launch(|_| {
.attach(AdHoc::on_launch("Launch Message", |_| {
println!("Rocket is about to launch!");
}))
.attach(AdHoc::on_request(|req, _| {
.attach(AdHoc::on_request("PUT Rewriter", |req, _| {
println!(" => Incoming request: {}", req);
if req.uri().path() == "/" {
println!(" => Changing method to `PUT`.");
req.set_method(Method::Put);
}
}))
.attach(AdHoc::on_response(|req, res| {
.attach(AdHoc::on_response("Response Rewriter", |req, res| {
if req.uri().path() == "/" {
println!(" => Rewriting response body.");
res.set_sized_body(Cursor::new("Hello, fairings!"));

View File

@ -195,7 +195,7 @@ fn assets(asset: PathBuf, assets_dir: State<AssetsDir>) -> Option<NamedFile> {
fn main() {
rocket::ignite()
.mount("/", routes![assets])
.attach(AdHoc::on_attach(|rocket| {
.attach(AdHoc::on_attach("Assets Config", |rocket| {
let assets_dir = rocket.config()
.get_str("assets_dir")
.unwrap_or("assets/")

View File

@ -194,22 +194,22 @@ function or closure. Using the `AdHoc` type is easy: simply call the
to create an `AdHoc` structure from a function or closure.
As an example, the code below creates a `Rocket` instance with two attached
ad-hoc fairings. The first, a launch fairing, simply prints a message indicating
that the application is about to the launch. The second, a request fairing,
changes the method of all requests to `PUT`.
ad-hoc fairings. The first, a launch fairing named "Launch Printer", simply
prints a message indicating that the application is about to the launch. The
second named "Put Rewriter", a request fairing, rewrites the method of all
requests to be `PUT`.
```rust
use rocket::fairing::AdHoc;
use rocket::http::Method;
rocket::ignite()
.attach(AdHoc::on_launch(|_| {
println!("Rocket is about to launch! Exciting!");
.attach(AdHoc::on_launch("Launch Printer", |_| {
println!("Rocket is about to launch! Exciting! Here we go...");
}))
.attach(AdHoc::on_request(|req, _| {
.attach(AdHoc::on_request("Put Rewriter", |req, _| {
req.set_method(Method::Put);
}));
```
[`AdHoc`]: https://api.rocket.rs/rocket/fairing/enum.AdHoc.html