2020-01-26 21:52:37 +00:00
|
|
|
#[macro_use] extern crate rocket;
|
|
|
|
|
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
|
|
|
use rocket::{Request, Rocket, Route, Catcher, Build, route, catcher};
|
2021-03-15 09:20:48 +00:00
|
|
|
use rocket::data::Data;
|
|
|
|
use rocket::http::{Method, Status};
|
2020-01-26 21:52:37 +00:00
|
|
|
use rocket::local::blocking::Client;
|
|
|
|
|
|
|
|
#[get("/panic")]
|
|
|
|
fn panic_route() -> &'static str {
|
|
|
|
panic!("Panic in route")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[catch(404)]
|
|
|
|
fn panic_catcher() -> &'static str {
|
|
|
|
panic!("Panic in catcher")
|
|
|
|
}
|
|
|
|
|
2021-03-06 09:37:36 +00:00
|
|
|
#[catch(500)]
|
|
|
|
fn ise() -> &'static str {
|
|
|
|
"Hey, sorry! :("
|
|
|
|
}
|
|
|
|
|
2021-04-14 01:58:05 +00:00
|
|
|
fn pre_future_route<'r>(_: &'r Request<'_>, _: Data) -> route::BoxFuture<'r> {
|
2021-03-15 09:20:48 +00:00
|
|
|
panic!("hey now...");
|
|
|
|
}
|
|
|
|
|
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
|
|
|
fn rocket() -> Rocket<Build> {
|
2021-04-08 08:07:52 +00:00
|
|
|
rocket::build()
|
2020-01-26 21:52:37 +00:00
|
|
|
.mount("/", routes![panic_route])
|
2021-03-26 04:36:00 +00:00
|
|
|
.mount("/", vec![Route::new(Method::Get, "/pre", pre_future_route)])
|
2020-01-26 21:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn catches_route_panic() {
|
2021-03-26 04:36:00 +00:00
|
|
|
let rocket = rocket().register("/", catchers![panic_catcher, ise]);
|
|
|
|
let client = Client::debug(rocket).unwrap();
|
2020-01-26 21:52:37 +00:00
|
|
|
let response = client.get("/panic").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::InternalServerError);
|
2021-03-06 09:37:36 +00:00
|
|
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
2020-01-26 21:52:37 +00:00
|
|
|
}
|
2021-03-15 09:20:48 +00:00
|
|
|
|
2020-01-26 21:52:37 +00:00
|
|
|
#[test]
|
|
|
|
fn catches_catcher_panic() {
|
2021-03-26 04:36:00 +00:00
|
|
|
let rocket = rocket().register("/", catchers![panic_catcher, ise]);
|
|
|
|
let client = Client::debug(rocket).unwrap();
|
2021-03-06 09:37:36 +00:00
|
|
|
let response = client.get("/noroute").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::InternalServerError);
|
|
|
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn catches_double_panic() {
|
2021-03-26 04:36:00 +00:00
|
|
|
#[catch(500)]
|
|
|
|
fn double_panic() {
|
|
|
|
panic!("so, so sorry...")
|
|
|
|
}
|
|
|
|
|
|
|
|
let rocket = rocket().register("/", catchers![panic_catcher, double_panic]);
|
Test 'secret_key' validation, now on pre-launch.
Prior to this commit, it was not possible to test Rocket crates in
production mode without setting a global secret key or bypassing secret
key checking - the testing script did the latter. The consequence is
that it became impossible to test secret key related failures because
the tests passed regardless.
This commit undoes this. As a consequence, all tests are now aware of
the difference between debug and release configurations, the latter of
which validates 'secret_key' by default. New 'Client::debug()' and
'Client::debug_with()' simplify creating an instance of 'Client' with
configuration in debug mode to avoid undesired test failures.
The summary of changes in this commit are:
* Config 'secret_key' success and failure are now tested.
* 'secret_key' validation was moved to pre-launch from 'Config:from()'.
* 'Config::from()' only extracts the config.
* Added 'Config::try_from()' for non-panicking extraction.
* 'Config' now knows the profile it was extracted from.
* The 'Config' provider sets a profile of 'Config.profile'.
* 'Rocket', 'Client', 'Fairings', implement 'Debug'.
* 'fairing::Info' implements 'Copy', 'Clone'.
* 'Fairings' keeps track of, logs attach fairings.
* 'Rocket::reconfigure()' was added to allow modifying a config.
Internally, the testing script was refactored to properly test the
codebase with the new changes. In particular, it no longer sets a rustc
'cfg' to avoid secret-key checking.
Resolves #1543.
Fixes #1564.
2021-03-09 08:07:43 +00:00
|
|
|
let client = Client::debug(rocket).unwrap();
|
2020-01-26 21:52:37 +00:00
|
|
|
let response = client.get("/noroute").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::InternalServerError);
|
2021-03-15 09:20:48 +00:00
|
|
|
assert!(response.into_string().unwrap().contains("Rocket"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn catches_early_route_panic() {
|
2021-03-26 04:36:00 +00:00
|
|
|
let rocket = rocket().register("/", catchers![panic_catcher, ise]);
|
|
|
|
let client = Client::debug(rocket).unwrap();
|
2021-03-15 09:20:48 +00:00
|
|
|
let response = client.get("/pre").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::InternalServerError);
|
|
|
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn catches_early_catcher_panic() {
|
2021-04-14 01:58:05 +00:00
|
|
|
fn pre_future_catcher<'r>(_: Status, _: &'r Request) -> catcher::BoxFuture<'r> {
|
2021-03-26 04:36:00 +00:00
|
|
|
panic!("a panicking pre-future catcher")
|
|
|
|
}
|
2021-03-15 09:20:48 +00:00
|
|
|
|
2021-03-26 04:36:00 +00:00
|
|
|
let rocket = rocket()
|
|
|
|
.register("/", vec![Catcher::new(404, pre_future_catcher)])
|
|
|
|
.register("/", catchers![ise]);
|
|
|
|
|
|
|
|
let client = Client::debug(rocket).unwrap();
|
2021-03-15 09:20:48 +00:00
|
|
|
let response = client.get("/idontexist").dispatch();
|
|
|
|
assert_eq!(response.status(), Status::InternalServerError);
|
|
|
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
2020-01-26 21:52:37 +00:00
|
|
|
}
|