mirror of https://github.com/rwf2/Rocket.git
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.
This commit is contained in:
parent
bbbe362740
commit
4e06ee64aa
|
@ -66,7 +66,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prioritizes_brotli() {
|
fn test_prioritizes_brotli() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -90,7 +90,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_br_font() {
|
fn test_br_font() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/font")
|
.get("/font")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -114,7 +114,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fallback_gzip() {
|
fn test_fallback_gzip() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip"))
|
||||||
|
@ -137,7 +137,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_recompress() {
|
fn test_does_not_recompress() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/already_encoded")
|
.get("/already_encoded")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -160,7 +160,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_compress_explicit_identity() {
|
fn test_does_not_compress_explicit_identity() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/identity")
|
.get("/identity")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -178,7 +178,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ignore_exceptions() {
|
fn test_ignore_exceptions() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/image")
|
.get("/image")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -202,7 +202,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ignores_unimplemented_encodings() {
|
fn test_ignores_unimplemented_encodings() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate"))
|
.header(Header::new("Accept-Encoding", "deflate"))
|
||||||
|
@ -220,7 +220,7 @@ mod compress_responder_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_respects_identity_only() {
|
fn test_respects_identity_only() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "identity"))
|
.header(Header::new("Accept-Encoding", "identity"))
|
||||||
|
|
|
@ -85,7 +85,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prioritizes_brotli() {
|
fn test_prioritizes_brotli() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -109,7 +109,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_br_font() {
|
fn test_br_font() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/font")
|
.get("/font")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -133,7 +133,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fallback_gzip() {
|
fn test_fallback_gzip() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip"))
|
||||||
|
@ -156,7 +156,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_recompress() {
|
fn test_does_not_recompress() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/already_encoded")
|
.get("/already_encoded")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -179,7 +179,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_compress_explicit_identity() {
|
fn test_does_not_compress_explicit_identity() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/identity")
|
.get("/identity")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -197,7 +197,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_compress_image() {
|
fn test_does_not_compress_image() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/image")
|
.get("/image")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -215,7 +215,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ignores_unimplemented_encodings() {
|
fn test_ignores_unimplemented_encodings() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "deflate"))
|
.header(Header::new("Accept-Encoding", "deflate"))
|
||||||
|
@ -233,7 +233,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_respects_identity_only() {
|
fn test_respects_identity_only() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/")
|
.get("/")
|
||||||
.header(Header::new("Accept-Encoding", "identity"))
|
.header(Header::new("Accept-Encoding", "identity"))
|
||||||
|
@ -251,7 +251,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_does_not_compress_custom_exception() {
|
fn test_does_not_compress_custom_exception() {
|
||||||
let client = Client::tracked(rocket_tar_exception()).expect("valid rocket instance");
|
let client = Client::debug(rocket_tar_exception()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/tar")
|
.get("/tar")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
@ -269,7 +269,7 @@ mod compression_fairing_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_compress_custom_removed_exception() {
|
fn test_compress_custom_removed_exception() {
|
||||||
let client = Client::tracked(rocket_tar_exception()).expect("valid rocket instance");
|
let client = Client::debug(rocket_tar_exception()).expect("valid rocket instance");
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.get("/image")
|
.get("/image")
|
||||||
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
.header(Header::new("Accept-Encoding", "deflate, gzip, br"))
|
||||||
|
|
|
@ -32,7 +32,7 @@ mod helmet_tests {
|
||||||
macro_rules! dispatch {
|
macro_rules! dispatch {
|
||||||
($helmet:expr, $closure:expr) => {{
|
($helmet:expr, $closure:expr) => {{
|
||||||
let rocket = rocket::ignite().mount("/", routes![hello]).attach($helmet);
|
let rocket = rocket::ignite().mount("/", routes![hello]).attach($helmet);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
$closure(response)
|
$closure(response)
|
||||||
|
|
|
@ -69,7 +69,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_no_index() {
|
fn test_static_no_index() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket");
|
let client = Client::debug(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "no_index", REGULAR_FILES, true);
|
assert_all(&client, "no_index", REGULAR_FILES, true);
|
||||||
assert_all(&client, "no_index", HIDDEN_FILES, false);
|
assert_all(&client, "no_index", HIDDEN_FILES, false);
|
||||||
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false);
|
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false);
|
||||||
|
@ -77,7 +77,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_hidden() {
|
fn test_static_hidden() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket");
|
let client = Client::debug(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "dots", REGULAR_FILES, true);
|
assert_all(&client, "dots", REGULAR_FILES, true);
|
||||||
assert_all(&client, "dots", HIDDEN_FILES, true);
|
assert_all(&client, "dots", HIDDEN_FILES, true);
|
||||||
assert_all(&client, "dots", INDEXED_DIRECTORIES, false);
|
assert_all(&client, "dots", INDEXED_DIRECTORIES, false);
|
||||||
|
@ -85,7 +85,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_index() {
|
fn test_static_index() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket");
|
let client = Client::debug(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "index", REGULAR_FILES, true);
|
assert_all(&client, "index", REGULAR_FILES, true);
|
||||||
assert_all(&client, "index", HIDDEN_FILES, false);
|
assert_all(&client, "index", HIDDEN_FILES, false);
|
||||||
assert_all(&client, "index", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "index", INDEXED_DIRECTORIES, true);
|
||||||
|
@ -97,7 +97,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_all() {
|
fn test_static_all() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket");
|
let client = Client::debug(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "both", REGULAR_FILES, true);
|
assert_all(&client, "both", REGULAR_FILES, true);
|
||||||
assert_all(&client, "both", HIDDEN_FILES, true);
|
assert_all(&client, "both", HIDDEN_FILES, true);
|
||||||
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
|
||||||
|
@ -128,7 +128,7 @@ mod static_tests {
|
||||||
fn catch_two(a: &str, b: &str) -> String { format!("{}/{}", a, b) }
|
fn catch_two(a: &str, b: &str) -> String { format!("{}/{}", a, b) }
|
||||||
|
|
||||||
let rocket = rocket().mount("/default", routes![catch_one, catch_two]);
|
let rocket = rocket().mount("/default", routes![catch_one, catch_two]);
|
||||||
let client = Client::tracked(rocket).expect("valid rocket");
|
let client = Client::debug(rocket).expect("valid rocket");
|
||||||
|
|
||||||
let response = client.get("/default/ireallydontexist").dispatch();
|
let response = client.get("/default/ireallydontexist").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
@ -145,7 +145,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_redirection() {
|
fn test_redirection() {
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket");
|
let client = Client::debug(rocket()).expect("valid rocket");
|
||||||
|
|
||||||
// Redirection only happens if enabled, and doesn't affect index behaviour.
|
// Redirection only happens if enabled, and doesn't affect index behaviour.
|
||||||
let response = client.get("/no_index/inner").dispatch();
|
let response = client.get("/no_index/inner").dispatch();
|
||||||
|
|
|
@ -40,12 +40,10 @@ mod templates_tests {
|
||||||
Err("error reloading templates!".into())
|
Err("error reloading templates!".into())
|
||||||
}));
|
}));
|
||||||
|
|
||||||
match Client::untracked(rocket) {
|
let error = Client::debug(rocket).expect_err("client failure");
|
||||||
Err(e) => match e.kind() {
|
match error.kind() {
|
||||||
FailedFairings(failures) => assert_eq!(failures[0], "Templates"),
|
FailedFairings(failures) => assert_eq!(failures[0].name, "Templates"),
|
||||||
_ => panic!("Wrong kind of launch error"),
|
_ => panic!("Wrong kind of launch error"),
|
||||||
}
|
|
||||||
_ => panic!("Wrong kind of error"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +77,7 @@ mod templates_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_template_metadata_with_tera() {
|
fn test_template_metadata_with_tera() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
|
||||||
let response = client.get("/tera/txt_test").dispatch();
|
let response = client.get("/tera/txt_test").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
@ -119,7 +117,7 @@ mod templates_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_template_metadata_with_handlebars() {
|
fn test_template_metadata_with_handlebars() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
|
||||||
let response = client.get("/hbs/test").dispatch();
|
let response = client.get("/hbs/test").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
@ -156,7 +154,7 @@ mod templates_tests {
|
||||||
write_file(&reload_path, INITIAL_TEXT);
|
write_file(&reload_path, INITIAL_TEXT);
|
||||||
|
|
||||||
// set up the client. if we can't reload templates, then just quit
|
// set up the client. if we can't reload templates, then just quit
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let res = client.get("/is_reloading").dispatch();
|
let res = client.get("/is_reloading").dispatch();
|
||||||
if res.status() != Status::Ok {
|
if res.status() != Status::Ok {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -34,7 +34,7 @@ foo!("/hello/<name>", name);
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reexpansion() {
|
fn test_reexpansion() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![easy, hard, hi]);
|
let rocket = rocket::ignite().mount("/", routes![easy, hard, hi]);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.get("/easy/327").dispatch();
|
let response = client.get("/easy/327").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "easy id: 327");
|
assert_eq!(response.into_string().unwrap(), "easy id: 327");
|
||||||
|
@ -60,7 +60,7 @@ index!(i32);
|
||||||
#[test]
|
#[test]
|
||||||
fn test_index() {
|
fn test_index() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![index]).manage(100i32);
|
let rocket = rocket::ignite().mount("/", routes![index]).manage(100i32);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "Thing: 100");
|
assert_eq!(response.into_string().unwrap(), "Thing: 100");
|
||||||
|
|
|
@ -587,7 +587,7 @@ fn test_nested_multi() {
|
||||||
// Ok("hi")
|
// Ok("hi")
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// let client = Client::untracked(crate::ignite().mount("/", routes![form])).unwrap();
|
// let client = Client::debug_with(routes![form]).unwrap();
|
||||||
// let ct = "multipart/form-data; boundary=X-BOUNDARY"
|
// let ct = "multipart/form-data; boundary=X-BOUNDARY"
|
||||||
// .parse::<ContentType>()
|
// .parse::<ContentType>()
|
||||||
// .unwrap();
|
// .unwrap();
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub enum Foo<'r> {
|
||||||
|
|
||||||
#[rocket::async_test]
|
#[rocket::async_test]
|
||||||
async fn responder_foo() {
|
async fn responder_foo() {
|
||||||
let client = Client::tracked(rocket::ignite()).await.expect("valid rocket");
|
let client = Client::debug_with(vec![]).await.expect("valid rocket");
|
||||||
let local_req = client.get("/");
|
let local_req = client.get("/");
|
||||||
let req = local_req.inner();
|
let req = local_req.inner();
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ pub struct Bar<'r> {
|
||||||
|
|
||||||
#[rocket::async_test]
|
#[rocket::async_test]
|
||||||
async fn responder_bar() {
|
async fn responder_bar() {
|
||||||
let client = Client::tracked(rocket::ignite()).await.expect("valid rocket");
|
let client = Client::debug_with(vec![]).await.expect("valid rocket");
|
||||||
let local_req = client.get("/");
|
let local_req = client.get("/");
|
||||||
let req = local_req.inner();
|
let req = local_req.inner();
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ pub struct Baz {
|
||||||
|
|
||||||
#[rocket::async_test]
|
#[rocket::async_test]
|
||||||
async fn responder_baz() {
|
async fn responder_baz() {
|
||||||
let client = Client::tracked(rocket::ignite()).await.expect("valid rocket");
|
let client = Client::debug_with(vec![]).await.expect("valid rocket");
|
||||||
let local_req = client.get("/");
|
let local_req = client.get("/");
|
||||||
let req = local_req.inner();
|
let req = local_req.inner();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[macro_use]extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
|
||||||
use rocket::{Request, Data};
|
use rocket::{Request, Data};
|
||||||
use rocket::local::blocking::Client;
|
use rocket::local::blocking::Client;
|
||||||
|
@ -33,7 +33,7 @@ fn simple<'r>(simple: Simple<'r>) -> &'r str { simple.0 }
|
||||||
#[test]
|
#[test]
|
||||||
fn test_data() {
|
fn test_data() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![form, simple]);
|
let rocket = rocket::ignite().mount("/", routes![form, simple]);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.post("/f")
|
let response = client.post("/f")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn test_formats() {
|
||||||
.mount("/", routes![json, xml, json_long, msgpack_long, msgpack,
|
.mount("/", routes![json, xml, json_long, msgpack_long, msgpack,
|
||||||
plain, binary, other]);
|
plain, binary, other]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.post("/").header(ContentType::JSON).dispatch();
|
let response = client.post("/").header(ContentType::JSON).dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "json");
|
assert_eq!(response.into_string().unwrap(), "json");
|
||||||
|
@ -87,7 +87,7 @@ fn test_custom_formats() {
|
||||||
let rocket = rocket::ignite()
|
let rocket = rocket::ignite()
|
||||||
.mount("/", routes![get_foo, post_foo, get_bar_baz, put_bar_baz]);
|
.mount("/", routes![get_foo, post_foo, get_bar_baz, put_bar_baz]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let foo_a = Accept::new(&[MediaType::new("application", "foo").into()]);
|
let foo_a = Accept::new(&[MediaType::new("application", "foo").into()]);
|
||||||
let foo_ct = ContentType::new("application", "foo");
|
let foo_ct = ContentType::new("application", "foo");
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn get3(_number: u64) -> &'static str { "3" }
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ranking() {
|
fn test_ranking() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![get0, get1, get2, get3]);
|
let rocket = rocket::ignite().mount("/", routes![get0, get1, get2, get3]);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.get("/0").dispatch();
|
let response = client.get("/0").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "0");
|
assert_eq!(response.into_string().unwrap(), "0");
|
||||||
|
@ -44,7 +44,7 @@ fn test_rank_collision() {
|
||||||
use rocket::error::ErrorKind;
|
use rocket::error::ErrorKind;
|
||||||
|
|
||||||
let rocket = rocket::ignite().mount("/", routes![get0, get0b]);
|
let rocket = rocket::ignite().mount("/", routes![get0, get0b]);
|
||||||
let client_result = Client::tracked(rocket);
|
let client_result = Client::debug(rocket);
|
||||||
match client_result.as_ref().map_err(|e| e.kind()) {
|
match client_result.as_ref().map_err(|e| e.kind()) {
|
||||||
Err(ErrorKind::Collision(..)) => { /* o.k. */ },
|
Err(ErrorKind::Collision(..)) => { /* o.k. */ },
|
||||||
Ok(_) => panic!("client succeeded unexpectedly"),
|
Ok(_) => panic!("client succeeded unexpectedly"),
|
||||||
|
|
|
@ -25,7 +25,7 @@ fn test_raw_ident() {
|
||||||
.mount("/", routes![get, swap])
|
.mount("/", routes![get, swap])
|
||||||
.register(catchers![catch]);
|
.register(catchers![catch]);
|
||||||
|
|
||||||
let client = Client::untracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.get("/example?type=1").dispatch();
|
let response = client.get("/example?type=1").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "example is 1");
|
assert_eq!(response.into_string().unwrap(), "example is 1");
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn test_full_route() {
|
||||||
.mount("/1", routes![post1])
|
.mount("/1", routes![post1])
|
||||||
.mount("/2", routes![post2]);
|
.mount("/2", routes![post2]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let a = RawStr::new("A%20A");
|
let a = RawStr::new("A%20A");
|
||||||
let name = RawStr::new("Bob%20McDonald");
|
let name = RawStr::new("Bob%20McDonald");
|
||||||
|
@ -171,7 +171,7 @@ fn filtered_raw_query(bird: usize, color: &str, rest: Contextual<'_, Filtered<'_
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filtered_raw_query() {
|
fn test_filtered_raw_query() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![filtered_raw_query]);
|
let rocket = rocket::ignite().mount("/", routes![filtered_raw_query]);
|
||||||
let client = Client::untracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn run(client: &Client, birds: &[&str], colors: &[&str], cats: &[&str]) -> (Status, String) {
|
fn run(client: &Client, birds: &[&str], colors: &[&str], cats: &[&str]) -> (Status, String) {
|
||||||
|
@ -259,7 +259,7 @@ fn test_query_collection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_tests(rocket: rocket::Rocket) {
|
fn run_tests(rocket: rocket::Rocket) {
|
||||||
let client = Client::untracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let colors = &["blue", "green"];
|
let colors = &["blue", "green"];
|
||||||
let dog = &["name=Fido", "age=10"];
|
let dog = &["name=Fido", "age=10"];
|
||||||
|
@ -327,7 +327,7 @@ fn test_inclusive_segments() {
|
||||||
.mount("/", routes![segments])
|
.mount("/", routes![segments])
|
||||||
.mount("/", routes![segments_empty]);
|
.mount("/", routes![segments_empty]);
|
||||||
|
|
||||||
let client = Client::untracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let get = |uri| client.get(uri).dispatch().into_string().unwrap();
|
let get = |uri| client.get(uri).dispatch().into_string().unwrap();
|
||||||
|
|
||||||
assert_eq!(get("/"), "empty+");
|
assert_eq!(get("/"), "empty+");
|
||||||
|
|
|
@ -27,11 +27,7 @@ fn test_ignored_segments() {
|
||||||
ig_1, just_static, ig_2, ig_3, ig_1_static, ig_1_static_static, wrapped
|
ig_1, just_static, ig_2, ig_3, ig_1_static, ig_1_static_static, wrapped
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let client = match Client::untracked(rocket) {
|
let client = Client::debug(rocket).unwrap();
|
||||||
Ok(client) => client,
|
|
||||||
Err(e) => { drop(e); panic!("whoops") },
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(get_string(&client, "/foo"), "1");
|
assert_eq!(get_string(&client, "/foo"), "1");
|
||||||
assert_eq!(get_string(&client, "/bar"), "1");
|
assert_eq!(get_string(&client, "/bar"), "1");
|
||||||
assert_eq!(get_string(&client, "/static"), "static");
|
assert_eq!(get_string(&client, "/static"), "static");
|
||||||
|
|
|
@ -47,7 +47,7 @@ async-trait = "0.1.43"
|
||||||
|
|
||||||
[dependencies.state]
|
[dependencies.state]
|
||||||
git = "https://github.com/SergioBenitez/state.git"
|
git = "https://github.com/SergioBenitez/state.git"
|
||||||
rev = "7576652"
|
rev = "0a7457d2"
|
||||||
|
|
||||||
[dependencies.rocket_codegen]
|
[dependencies.rocket_codegen]
|
||||||
version = "0.5.0-dev"
|
version = "0.5.0-dev"
|
||||||
|
@ -74,6 +74,7 @@ version_check = "0.9.1"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bencher = "0.1"
|
bencher = "0.1"
|
||||||
figment = { version = "0.10", features = ["test"] }
|
figment = { version = "0.10", features = ["test"] }
|
||||||
|
pretty_assertions = "0.7"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "format-routing"
|
name = "format-routing"
|
||||||
|
|
|
@ -10,8 +10,12 @@ fn get() -> &'static str { "get" }
|
||||||
fn post() -> &'static str { "post" }
|
fn post() -> &'static str { "post" }
|
||||||
|
|
||||||
fn rocket() -> rocket::Rocket {
|
fn rocket() -> rocket::Rocket {
|
||||||
rocket::custom(rocket::Config::figment().merge(("log_level", "off")))
|
let config = rocket::Config {
|
||||||
.mount("/", routes![get, post])
|
log_level: rocket::config::LogLevel::Off,
|
||||||
|
..rocket::Config::debug_default()
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket::custom(config).mount("/", routes![get, post])
|
||||||
}
|
}
|
||||||
|
|
||||||
use bencher::Bencher;
|
use bencher::Bencher;
|
||||||
|
|
|
@ -20,7 +20,12 @@ fn post2() -> &'static str { "html" }
|
||||||
fn post3() -> &'static str { "plain" }
|
fn post3() -> &'static str { "plain" }
|
||||||
|
|
||||||
fn rocket() -> rocket::Rocket {
|
fn rocket() -> rocket::Rocket {
|
||||||
rocket::custom(rocket::Config::figment().merge(("log_level", "off")))
|
let config = rocket::Config {
|
||||||
|
log_level: rocket::config::LogLevel::Off,
|
||||||
|
..rocket::Config::debug_default()
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket::custom(config)
|
||||||
.mount("/", routes![get, get2, get3])
|
.mount("/", routes![get, get2, get3])
|
||||||
.mount("/", routes![post, post2, post3])
|
.mount("/", routes![post, post2, post3])
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,11 @@ fn index_c() -> &'static str { "index" }
|
||||||
fn index_dyn_a(_a: &str) -> &'static str { "index" }
|
fn index_dyn_a(_a: &str) -> &'static str { "index" }
|
||||||
|
|
||||||
fn hello_world_rocket() -> rocket::Rocket {
|
fn hello_world_rocket() -> rocket::Rocket {
|
||||||
let config = rocket::Config::figment().merge(("log_level", "off"));
|
let config = rocket::Config {
|
||||||
|
log_level: rocket::config::LogLevel::Off,
|
||||||
|
..rocket::Config::debug_default()
|
||||||
|
};
|
||||||
|
|
||||||
rocket::custom(config).mount("/", routes![hello_world])
|
rocket::custom(config).mount("/", routes![hello_world])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ use crate::config::SecretKey;
|
||||||
///
|
///
|
||||||
/// * **Profile**
|
/// * **Profile**
|
||||||
///
|
///
|
||||||
/// This provider does not set a profile.
|
/// The profile is set to the value of the `profile` field.
|
||||||
///
|
///
|
||||||
/// * **Metadata**
|
/// * **Metadata**
|
||||||
///
|
///
|
||||||
|
@ -54,6 +54,12 @@ use crate::config::SecretKey;
|
||||||
/// Note that these behaviors differ from those of [`Config::figment()`].
|
/// Note that these behaviors differ from those of [`Config::figment()`].
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
/// The selected profile. **(default: _debug_ `debug` / _release_ `release`)**
|
||||||
|
///
|
||||||
|
/// **Note:** This field is never serialized nor deserialized. It is set to
|
||||||
|
/// the value of the selected `Profile` during extraction.
|
||||||
|
#[serde(skip)]
|
||||||
|
pub profile: Profile,
|
||||||
/// IP address to serve on. **(default: `127.0.0.1`)**
|
/// IP address to serve on. **(default: `127.0.0.1`)**
|
||||||
pub address: IpAddr,
|
pub address: IpAddr,
|
||||||
/// Port to serve on. **(default: `8000`)**
|
/// Port to serve on. **(default: `8000`)**
|
||||||
|
@ -106,10 +112,10 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// The default "debug" profile.
|
/// The default debug profile: `debug`.
|
||||||
pub const DEBUG_PROFILE: Profile = Profile::const_new("debug");
|
pub const DEBUG_PROFILE: Profile = Profile::const_new("debug");
|
||||||
|
|
||||||
/// The default "release" profile.
|
/// The default release profile: `release`.
|
||||||
pub const RELEASE_PROFILE: Profile = Profile::const_new("release");
|
pub const RELEASE_PROFILE: Profile = Profile::const_new("release");
|
||||||
|
|
||||||
/// The default profile: "debug" on `debug`, "release" on `release`.
|
/// The default profile: "debug" on `debug`, "release" on `release`.
|
||||||
|
@ -145,6 +151,7 @@ impl Config {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn debug_default() -> Config {
|
pub fn debug_default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
|
profile: Self::DEBUG_PROFILE,
|
||||||
address: Ipv4Addr::new(127, 0, 0, 1).into(),
|
address: Ipv4Addr::new(127, 0, 0, 1).into(),
|
||||||
port: 8000,
|
port: 8000,
|
||||||
workers: num_cpus::get(),
|
workers: num_cpus::get(),
|
||||||
|
@ -177,6 +184,7 @@ impl Config {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn release_default() -> Config {
|
pub fn release_default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
|
profile: Self::RELEASE_PROFILE,
|
||||||
log_level: LogLevel::Critical,
|
log_level: LogLevel::Critical,
|
||||||
..Config::debug_default()
|
..Config::debug_default()
|
||||||
}
|
}
|
||||||
|
@ -217,52 +225,55 @@ impl Config {
|
||||||
.merge(Env::prefixed("ROCKET_").ignore(&["PROFILE"]).global())
|
.merge(Env::prefixed("ROCKET_").ignore(&["PROFILE"]).global())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to extract a `Config` from `provider`.
|
/// Attempts to extract a `Config` from `provider`, returning the result.
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// If extraction fails, prints an error message indicating the failure and
|
|
||||||
/// panics.
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use figment::{Figment, providers::{Toml, Format, Env}};
|
/// use rocket::Config;
|
||||||
|
/// use rocket::figment::providers::{Toml, Format, Env};
|
||||||
///
|
///
|
||||||
/// // Use Rocket's default `Figment`, but allow values from `MyApp.toml`
|
/// // Use Rocket's default `Figment`, but allow values from `MyApp.toml`
|
||||||
/// // and `MY_APP_` prefixed environment variables to supersede its values.
|
/// // and `MY_APP_` prefixed environment variables to supersede its values.
|
||||||
/// let figment = rocket::Config::figment()
|
/// let figment = Config::figment()
|
||||||
|
/// .merge(("some-thing", 123))
|
||||||
|
/// .merge(Env::prefixed("CONFIG_"));
|
||||||
|
///
|
||||||
|
/// let config = Config::try_from(figment);
|
||||||
|
/// ```
|
||||||
|
pub fn try_from<T: Provider>(provider: T) -> Result<Self> {
|
||||||
|
let figment = Figment::from(provider);
|
||||||
|
let mut config = figment.extract::<Self>()?;
|
||||||
|
config.profile = figment.profile().clone();
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract a `Config` from `provider`, panicking if extraction fails.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If extraction fails, prints an error message indicating the failure and
|
||||||
|
/// panics. For a version that doesn't panic, use [`Config::try_from()`].
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::Config;
|
||||||
|
/// use rocket::figment::providers::{Toml, Format, Env};
|
||||||
|
///
|
||||||
|
/// // Use Rocket's default `Figment`, but allow values from `MyApp.toml`
|
||||||
|
/// // and `MY_APP_` prefixed environment variables to supersede its values.
|
||||||
|
/// let figment = Config::figment()
|
||||||
/// .merge(Toml::file("MyApp.toml").nested())
|
/// .merge(Toml::file("MyApp.toml").nested())
|
||||||
/// .merge(Env::prefixed("MY_APP_"));
|
/// .merge(Env::prefixed("MY_APP_"));
|
||||||
///
|
///
|
||||||
/// let config = rocket::Config::from(figment);
|
/// let config = Config::from(figment);
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
|
||||||
pub fn from<T: Provider>(provider: T) -> Self {
|
pub fn from<T: Provider>(provider: T) -> Self {
|
||||||
let figment = Figment::from(&provider);
|
Self::try_from(provider).unwrap_or_else(|e| {
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut config = figment.extract::<Self>().unwrap_or_else(|e| {
|
|
||||||
pretty_print_error(e);
|
pretty_print_error(e);
|
||||||
panic!("aborting due to configuration error(s)")
|
panic!("aborting due to configuration error(s)")
|
||||||
});
|
})
|
||||||
|
|
||||||
#[cfg(all(feature = "secrets", not(test), not(rocket_unsafe_secret_key)))]
|
|
||||||
if !config.secret_key.is_provided() {
|
|
||||||
if figment.profile() == Self::DEBUG_PROFILE {
|
|
||||||
// in debug, try to generate a key for a bit more security
|
|
||||||
let key = SecretKey::generate().unwrap_or(SecretKey::zero());
|
|
||||||
config.secret_key = key;
|
|
||||||
} else {
|
|
||||||
crate::logger::try_init(LogLevel::Debug, true, false);
|
|
||||||
error!("secrets enabled in non-debug without `secret_key`");
|
|
||||||
info_!("selected profile: {}", Paint::white(figment.profile()));
|
|
||||||
info_!("disable `secrets` feature or configure a `secret_key`");
|
|
||||||
panic!("aborting due to configuration error(s)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if TLS is enabled.
|
/// Returns `true` if TLS is enabled.
|
||||||
|
@ -306,17 +317,8 @@ impl Config {
|
||||||
false => launch_info_!("tls: {}", Paint::default("disabled").bold()),
|
false => launch_info_!("tls: {}", Paint::default("disabled").bold()),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "secrets", not(test), not(rocket_unsafe_secret_key)))] {
|
#[cfg(feature = "secrets")]
|
||||||
launch_info_!("secret key: {:?}",
|
launch_info_!("secret key: {:?}", Paint::default(&self.secret_key).bold());
|
||||||
Paint::default(&self.secret_key).bold());
|
|
||||||
|
|
||||||
if !self.secret_key.is_provided() {
|
|
||||||
warn!("secrets enabled without a configured `secret_key`");
|
|
||||||
info_!("disable `secrets` feature or configure a `secret_key`");
|
|
||||||
info_!("this becomes a {} in non-debug profiles",
|
|
||||||
Paint::red("hard error").bold());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch_info_!("temp dir: {}", Paint::default(&self.temp_dir.display()).bold());
|
launch_info_!("temp dir: {}", Paint::default(&self.temp_dir.display()).bold());
|
||||||
launch_info_!("log level: {}", Paint::default(self.log_level).bold());
|
launch_info_!("log level: {}", Paint::default(self.log_level).bold());
|
||||||
|
@ -372,6 +374,9 @@ impl Provider for Config {
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn profile(&self) -> Option<Profile> {
|
||||||
|
Some(self.profile.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
|
@ -387,7 +392,9 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'r Config {
|
||||||
pub fn pretty_print_error(error: figment::Error) {
|
pub fn pretty_print_error(error: figment::Error) {
|
||||||
use figment::error::{Kind, OneOf};
|
use figment::error::{Kind, OneOf};
|
||||||
|
|
||||||
crate::logger::try_init(LogLevel::Debug, true, false);
|
let mut config = Config::debug_default();
|
||||||
|
config.log_level = LogLevel::Debug;
|
||||||
|
crate::logger::init(&config);
|
||||||
|
|
||||||
error!("Rocket configuration extraction from provider failed.");
|
error!("Rocket configuration extraction from provider failed.");
|
||||||
for e in error {
|
for e in error {
|
||||||
|
|
|
@ -130,7 +130,8 @@ pub use secret_key::SecretKey;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use figment::Figment;
|
use figment::{Figment, Profile};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::config::{Config, TlsConfig};
|
use crate::config::{Config, TlsConfig};
|
||||||
use crate::logger::LogLevel;
|
use crate::logger::LogLevel;
|
||||||
|
@ -140,19 +141,10 @@ mod tests {
|
||||||
fn test_default_round_trip() {
|
fn test_default_round_trip() {
|
||||||
figment::Jail::expect_with(|_| {
|
figment::Jail::expect_with(|_| {
|
||||||
let original = Config::figment();
|
let original = Config::figment();
|
||||||
let profile = original.profile().clone();
|
let roundtrip = Figment::from(Config::from(&original));
|
||||||
let roundtrip = Figment::from(Config::from(&original)).select(profile);
|
|
||||||
for figment in &[original, roundtrip] {
|
for figment in &[original, roundtrip] {
|
||||||
assert_eq!(figment.profile(), Config::DEFAULT_PROFILE);
|
let config = Config::from(figment);
|
||||||
|
|
||||||
#[cfg(debug_assertions)] assert_eq!(figment.profile(), Config::DEBUG_PROFILE);
|
|
||||||
#[cfg(not(debug_assertions))] assert_eq!(figment.profile(), Config::RELEASE_PROFILE);
|
|
||||||
|
|
||||||
let config: Config = figment.extract().unwrap();
|
|
||||||
assert_eq!(config, Config::default());
|
assert_eq!(config, Config::default());
|
||||||
|
|
||||||
#[cfg(debug_assertions)] assert_eq!(config, Config::debug_default());
|
|
||||||
#[cfg(not(debug_assertions))] assert_eq!(config, Config::release_default());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -305,6 +297,7 @@ mod tests {
|
||||||
jail.set_env("ROCKET_PROFILE", "unknown");
|
jail.set_env("ROCKET_PROFILE", "unknown");
|
||||||
let config = Config::from(Config::figment());
|
let config = Config::from(Config::figment());
|
||||||
assert_eq!(config, Config {
|
assert_eq!(config, Config {
|
||||||
|
profile: Profile::const_new("unknown"),
|
||||||
limits: Limits::default()
|
limits: Limits::default()
|
||||||
.limit("stream", 50.kilobytes())
|
.limit("stream", 50.kilobytes())
|
||||||
.limit("forms", 2.kilobytes()),
|
.limit("forms", 2.kilobytes()),
|
||||||
|
@ -314,6 +307,7 @@ mod tests {
|
||||||
jail.set_env("ROCKET_PROFILE", "debug");
|
jail.set_env("ROCKET_PROFILE", "debug");
|
||||||
let config = Config::from(Config::figment());
|
let config = Config::from(Config::figment());
|
||||||
assert_eq!(config, Config {
|
assert_eq!(config, Config {
|
||||||
|
profile: Profile::const_new("debug"),
|
||||||
limits: Limits::default()
|
limits: Limits::default()
|
||||||
.limit("stream", 50.kilobytes())
|
.limit("stream", 50.kilobytes())
|
||||||
.limit("forms", 2.kilobytes())
|
.limit("forms", 2.kilobytes())
|
||||||
|
@ -404,4 +398,60 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "secrets")]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_err_on_non_debug_and_no_secret_key() {
|
||||||
|
figment::Jail::expect_with(|jail| {
|
||||||
|
jail.set_env("ROCKET_PROFILE", "release");
|
||||||
|
let rocket = crate::custom(Config::figment());
|
||||||
|
let _result = crate::local::blocking::Client::untracked(rocket);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "secrets")]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_err_on_non_debug2_and_no_secret_key() {
|
||||||
|
figment::Jail::expect_with(|jail| {
|
||||||
|
jail.set_env("ROCKET_PROFILE", "boop");
|
||||||
|
let rocket = crate::custom(Config::figment());
|
||||||
|
let _result = crate::local::blocking::Client::tracked(rocket);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_err_on_debug_and_no_secret_key() {
|
||||||
|
figment::Jail::expect_with(|jail| {
|
||||||
|
jail.set_env("ROCKET_PROFILE", "debug");
|
||||||
|
let figment = Config::figment();
|
||||||
|
assert!(crate::local::blocking::Client::untracked(crate::custom(&figment)).is_ok());
|
||||||
|
crate::async_main(async {
|
||||||
|
let rocket = crate::custom(&figment);
|
||||||
|
assert!(crate::local::asynchronous::Client::tracked(rocket).await.is_ok());
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_err_on_release_and_custom_secret_key() {
|
||||||
|
figment::Jail::expect_with(|jail| {
|
||||||
|
jail.set_env("ROCKET_PROFILE", "release");
|
||||||
|
let key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk=";
|
||||||
|
let figment = Config::figment().merge(("secret_key", key));
|
||||||
|
|
||||||
|
assert!(crate::local::blocking::Client::tracked(crate::custom(&figment)).is_ok());
|
||||||
|
crate::async_main(async {
|
||||||
|
let rocket = crate::custom(&figment);
|
||||||
|
assert!(crate::local::asynchronous::Client::untracked(rocket).await.is_ok());
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,34 +30,40 @@ enum Kind {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// When configured in the debug profile with the `secrets` feature enabled, a
|
/// When configured in the debug profile with the `secrets` feature enabled, a
|
||||||
/// key set a `0` is automatically regenerated from the OS's random source if
|
/// key set as `0` is automatically regenerated at launch time from the OS's
|
||||||
/// available.
|
/// random source if available.
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # // FIXME: Don't special case `SecretKey`.
|
|
||||||
/// use rocket::config::Config;
|
/// use rocket::config::Config;
|
||||||
|
/// use rocket::local::blocking::Client;
|
||||||
///
|
///
|
||||||
/// let figment = Config::figment()
|
/// let figment = Config::figment()
|
||||||
/// .merge(("secret_key", vec![0u8; 64]))
|
/// .merge(("secret_key", vec![0u8; 64]))
|
||||||
/// .select("debug");
|
/// .select("debug");
|
||||||
///
|
///
|
||||||
/// let config = Config::from(figment);
|
/// let rocket = rocket::custom(figment);
|
||||||
/// assert!(!config.secret_key.is_zero());
|
/// let client = Client::tracked(rocket).expect("okay in debug");
|
||||||
|
/// assert!(!client.rocket().config().secret_key.is_zero());
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// When running in any other profile with the `secrets` feature enabled,
|
/// When running in any other profile with the `secrets` feature enabled,
|
||||||
/// providing a key of `0` or not provided a key at all results in a failure at
|
/// providing a key of `0` or not provided a key at all results in a failure at
|
||||||
/// launch-time:
|
/// launch-time:
|
||||||
///
|
///
|
||||||
/// ```rust,should_panic,ignore
|
/// ```rust
|
||||||
/// # // FIXME: Don't special case `SecretKey` checking on test/unsafe_key.
|
|
||||||
/// use rocket::config::Config;
|
/// use rocket::config::Config;
|
||||||
|
/// use rocket::figment::Profile;
|
||||||
|
/// use rocket::local::blocking::Client;
|
||||||
|
/// use rocket::error::ErrorKind;
|
||||||
///
|
///
|
||||||
|
/// let profile = Profile::const_new("staging");
|
||||||
/// let figment = Config::figment()
|
/// let figment = Config::figment()
|
||||||
/// .merge(("secret_key", vec![0u8; 64]))
|
/// .merge(("secret_key", vec![0u8; 64]))
|
||||||
/// .select("staging");
|
/// .select(profile.clone());
|
||||||
///
|
///
|
||||||
/// let config = Config::from(figment);
|
/// let rocket = rocket::custom(figment);
|
||||||
|
/// let error = Client::tracked(rocket).expect_err("failure in non-debug");
|
||||||
|
/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile)));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies
|
/// [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies
|
||||||
|
|
|
@ -47,8 +47,7 @@ pub use self::cookie::{Cookie, SameSite, Iter};
|
||||||
/// }
|
/// }
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// # use rocket::local::blocking::Client;
|
/// # use rocket::local::blocking::Client;
|
||||||
/// # let rocket = rocket::ignite().mount("/", routes![message]);
|
/// # let client = Client::debug_with(routes![message]).unwrap();
|
||||||
/// # let client = Client::tracked(rocket).unwrap();
|
|
||||||
/// # let response = client.get("/message")
|
/// # let response = client.get("/message")
|
||||||
/// # .cookie(Cookie::new("message", "hi"))
|
/// # .cookie(Cookie::new("message", "hi"))
|
||||||
/// # .dispatch();
|
/// # .dispatch();
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::{io, fmt};
|
||||||
use std::sync::atomic::{Ordering, AtomicBool};
|
use std::sync::atomic::{Ordering, AtomicBool};
|
||||||
|
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
use figment::Profile;
|
||||||
|
|
||||||
use crate::router::Route;
|
use crate::router::Route;
|
||||||
|
|
||||||
|
@ -80,8 +81,10 @@ pub enum ErrorKind {
|
||||||
Runtime(Box<dyn std::error::Error + Send + Sync>),
|
Runtime(Box<dyn std::error::Error + Send + Sync>),
|
||||||
/// Route collisions were detected.
|
/// Route collisions were detected.
|
||||||
Collision(Vec<(Route, Route)>),
|
Collision(Vec<(Route, Route)>),
|
||||||
/// A launch fairing reported an error.
|
/// Launch fairing(s) failed.
|
||||||
FailedFairings(Vec<&'static str>),
|
FailedFairings(Vec<crate::fairing::Info>),
|
||||||
|
/// The configuration profile is not debug but not secret key is configured.
|
||||||
|
InsecureSecretKey(Profile),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ErrorKind> for Error {
|
impl From<ErrorKind> for Error {
|
||||||
|
@ -137,9 +140,10 @@ impl fmt::Display for ErrorKind {
|
||||||
match self {
|
match self {
|
||||||
ErrorKind::Bind(e) => write!(f, "binding failed: {}", e),
|
ErrorKind::Bind(e) => write!(f, "binding failed: {}", e),
|
||||||
ErrorKind::Io(e) => write!(f, "I/O error: {}", e),
|
ErrorKind::Io(e) => write!(f, "I/O error: {}", e),
|
||||||
ErrorKind::Collision(_) => write!(f, "route collisions detected"),
|
ErrorKind::Collision(_) => "route collisions detected".fmt(f),
|
||||||
ErrorKind::FailedFairings(_) => write!(f, "a launch fairing failed"),
|
ErrorKind::FailedFairings(_) => "a launch fairing failed".fmt(f),
|
||||||
ErrorKind::Runtime(e) => write!(f, "runtime error: {}", e)
|
ErrorKind::Runtime(e) => write!(f, "runtime error: {}", e),
|
||||||
|
ErrorKind::InsecureSecretKey(_) => "insecure secret key config".fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +170,7 @@ impl Drop for Error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
match *self.kind() {
|
match self.kind() {
|
||||||
ErrorKind::Bind(ref e) => {
|
ErrorKind::Bind(ref e) => {
|
||||||
error!("Rocket failed to bind network socket to given address/port.");
|
error!("Rocket failed to bind network socket to given address/port.");
|
||||||
info_!("{}", e);
|
info_!("{}", e);
|
||||||
|
@ -189,7 +193,7 @@ impl Drop for Error {
|
||||||
ErrorKind::FailedFairings(ref failures) => {
|
ErrorKind::FailedFairings(ref failures) => {
|
||||||
error!("Rocket failed to launch due to failing fairings:");
|
error!("Rocket failed to launch due to failing fairings:");
|
||||||
for fairing in failures {
|
for fairing in failures {
|
||||||
info_!("{}", fairing);
|
info_!("{}", fairing.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("aborting due to launch fairing failure");
|
panic!("aborting due to launch fairing failure");
|
||||||
|
@ -199,6 +203,12 @@ impl Drop for Error {
|
||||||
info_!("{}", err);
|
info_!("{}", err);
|
||||||
panic!("aborting due to runtime failure");
|
panic!("aborting due to runtime failure");
|
||||||
}
|
}
|
||||||
|
ErrorKind::InsecureSecretKey(profile) => {
|
||||||
|
error!("secrets enabled in non-debug without `secret_key`");
|
||||||
|
info_!("selected profile: {}", Paint::white(profile));
|
||||||
|
info_!("disable `secrets` feature or configure a `secret_key`");
|
||||||
|
panic!("aborting due to insecure configuration")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{Rocket, Request, Response, Data};
|
use crate::{Rocket, Request, Response, Data};
|
||||||
use crate::fairing::{Fairing, Kind};
|
use crate::fairing::{Fairing, Info, Kind};
|
||||||
use crate::logger::PaintExt;
|
use crate::logger::PaintExt;
|
||||||
|
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
@ -7,8 +7,9 @@ use yansi::Paint;
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Fairings {
|
pub struct Fairings {
|
||||||
all_fairings: Vec<Box<dyn Fairing>>,
|
all_fairings: Vec<Box<dyn Fairing>>,
|
||||||
attach_failures: Vec<&'static str>,
|
attach_failures: Vec<Info>,
|
||||||
// The vectors below hold indices into `all_fairings`.
|
// The vectors below hold indices into `all_fairings`.
|
||||||
|
attach: Vec<usize>,
|
||||||
launch: Vec<usize>,
|
launch: Vec<usize>,
|
||||||
request: Vec<usize>,
|
request: Vec<usize>,
|
||||||
response: Vec<usize>,
|
response: Vec<usize>,
|
||||||
|
@ -23,26 +24,39 @@ impl Fairings {
|
||||||
pub async fn attach(&mut self, fairing: Box<dyn Fairing>, mut rocket: Rocket) -> Rocket {
|
pub async fn attach(&mut self, fairing: Box<dyn Fairing>, mut rocket: Rocket) -> Rocket {
|
||||||
// Run the `on_attach` callback if this is an 'attach' fairing.
|
// Run the `on_attach` callback if this is an 'attach' fairing.
|
||||||
let kind = fairing.info().kind;
|
let kind = fairing.info().kind;
|
||||||
let name = fairing.info().name;
|
let fairing = self.add(fairing);
|
||||||
if kind.is(Kind::Attach) {
|
if kind.is(Kind::Attach) {
|
||||||
|
let info = fairing.info();
|
||||||
rocket = fairing.on_attach(rocket).await
|
rocket = fairing.on_attach(rocket).await
|
||||||
.unwrap_or_else(|r| { self.attach_failures.push(name); r })
|
.unwrap_or_else(|r| { self.attach_failures.push(info); r })
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add(fairing);
|
|
||||||
rocket
|
rocket
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&mut self, fairing: Box<dyn Fairing>) {
|
fn add(&mut self, fairing: Box<dyn Fairing>) -> &dyn Fairing {
|
||||||
let kind = fairing.info().kind;
|
let kind = fairing.info().kind;
|
||||||
if !kind.is_exactly(Kind::Attach) {
|
let index = self.all_fairings.len();
|
||||||
let index = self.all_fairings.len();
|
self.all_fairings.push(fairing);
|
||||||
self.all_fairings.push(fairing);
|
|
||||||
|
|
||||||
if kind.is(Kind::Launch) { self.launch.push(index); }
|
if kind.is(Kind::Attach) { self.attach.push(index); }
|
||||||
if kind.is(Kind::Request) { self.request.push(index); }
|
if kind.is(Kind::Launch) { self.launch.push(index); }
|
||||||
if kind.is(Kind::Response) { self.response.push(index); }
|
if kind.is(Kind::Request) { self.request.push(index); }
|
||||||
}
|
if kind.is(Kind::Response) { self.response.push(index); }
|
||||||
|
|
||||||
|
&*self.all_fairings[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn fairings(&self, kind: Kind) -> impl Iterator<Item = &dyn Fairing> {
|
||||||
|
let indices = match kind {
|
||||||
|
k if k.is(Kind::Attach) => &self.attach,
|
||||||
|
k if k.is(Kind::Launch) => &self.launch,
|
||||||
|
k if k.is(Kind::Request) => &self.request,
|
||||||
|
_ => &self.response,
|
||||||
|
};
|
||||||
|
|
||||||
|
indices.iter().map(move |i| &*self.all_fairings[*i])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, others: Fairings) {
|
pub fn append(&mut self, others: Fairings) {
|
||||||
|
@ -53,26 +67,26 @@ impl Fairings {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn handle_launch(&self, rocket: &Rocket) {
|
pub fn handle_launch(&self, rocket: &Rocket) {
|
||||||
for &i in &self.launch {
|
for fairing in self.fairings(Kind::Launch) {
|
||||||
self.all_fairings[i].on_launch(rocket);
|
fairing.on_launch(rocket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data) {
|
pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data) {
|
||||||
for &i in &self.request {
|
for fairing in self.fairings(Kind::Request) {
|
||||||
self.all_fairings[i].on_request(req, data).await;
|
fairing.on_request(req, data).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub async fn handle_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
|
pub async fn handle_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
|
||||||
for &i in &self.response {
|
for fairing in self.fairings(Kind::Response) {
|
||||||
self.all_fairings[i].on_response(request, response).await;
|
fairing.on_response(request, response).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn failures(&self) -> Option<&[&'static str]> {
|
pub fn failures(&self) -> Option<&[Info]> {
|
||||||
if self.attach_failures.is_empty() {
|
if self.attach_failures.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,24 +94,35 @@ impl Fairings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn info_for(&self, kind: &str, fairings: &[usize]) {
|
|
||||||
if !fairings.is_empty() {
|
|
||||||
let num = fairings.len();
|
|
||||||
let names = fairings.iter().cloned()
|
|
||||||
.map(|i| self.all_fairings[i].info().name)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
info_!("{} {}: {}", Paint::default(num).bold(), kind, Paint::default(names).bold());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pretty_print_counts(&self) {
|
pub fn pretty_print_counts(&self) {
|
||||||
|
fn pretty_print(f: &Fairings, prefix: &str, kind: Kind) {
|
||||||
|
let names: Vec<_> = f.fairings(kind).map(|f| f.info().name).collect();
|
||||||
|
let num = names.len();
|
||||||
|
let joined = names.join(", ");
|
||||||
|
info_!("{} {}: {}", Paint::default(num).bold(), prefix, Paint::default(joined).bold());
|
||||||
|
}
|
||||||
|
|
||||||
if !self.all_fairings.is_empty() {
|
if !self.all_fairings.is_empty() {
|
||||||
info!("{}{}:", Paint::emoji("📡 "), Paint::magenta("Fairings"));
|
info!("{}{}:", Paint::emoji("📡 "), Paint::magenta("Fairings"));
|
||||||
self.info_for("launch", &self.launch);
|
pretty_print(self, "attach", Kind::Attach);
|
||||||
self.info_for("request", &self.request);
|
pretty_print(self, "launch", Kind::Launch);
|
||||||
self.info_for("response", &self.response);
|
pretty_print(self, "request", Kind::Request);
|
||||||
|
pretty_print(self, "response", Kind::Response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Fairings {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
fn debug_info(fs: &Fairings, kind: Kind) -> Vec<Info> {
|
||||||
|
fs.fairings(kind).map(|f| f.info()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
f.debug_struct("Fairings")
|
||||||
|
.field("attach", &debug_info(self, Kind::Attach))
|
||||||
|
.field("launch", &debug_info(self, Kind::Launch))
|
||||||
|
.field("request", &debug_info(self, Kind::Request))
|
||||||
|
.field("response", &debug_info(self, Kind::Response))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use std::ops::BitOr;
|
||||||
/// }
|
/// }
|
||||||
/// # ;
|
/// # ;
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Info {
|
pub struct Info {
|
||||||
/// The name of the fairing.
|
/// The name of the fairing.
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
|
|
@ -35,7 +35,7 @@ use crate::error::Error;
|
||||||
/// The following snippet creates a `Client` from a `Rocket` instance and
|
/// The following snippet creates a `Client` from a `Rocket` instance and
|
||||||
/// dispatches a local `POST /` request with a body of `Hello, world!`.
|
/// dispatches a local `POST /` request with a body of `Hello, world!`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// use rocket::local::asynchronous::Client;
|
/// use rocket::local::asynchronous::Client;
|
||||||
///
|
///
|
||||||
/// # rocket::async_test(async {
|
/// # rocket::async_test(async {
|
||||||
|
@ -69,8 +69,7 @@ impl Client {
|
||||||
where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send
|
where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send
|
||||||
{
|
{
|
||||||
crate::async_test(async {
|
crate::async_test(async {
|
||||||
let rocket = crate::ignite();
|
let client = Client::debug(crate::ignite()).await.unwrap();
|
||||||
let client = Client::untracked(rocket).await.expect("valid rocket");
|
|
||||||
let request = client.get("/");
|
let request = client.get("/");
|
||||||
let response = request.clone().dispatch().await;
|
let response = request.clone().dispatch().await;
|
||||||
f(&client, request, response)
|
f(&client, request, response)
|
||||||
|
@ -107,6 +106,12 @@ impl Client {
|
||||||
pub_client_impl!("use rocket::local::asynchronous::Client;" @async await);
|
pub_client_impl!("use rocket::local::asynchronous::Client;" @async await);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Client {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self._rocket().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -14,7 +14,7 @@ use super::{Client, LocalResponse};
|
||||||
/// The following snippet uses the available builder methods to construct and
|
/// The following snippet uses the available builder methods to construct and
|
||||||
/// dispatch a `POST` request to `/` with a JSON body:
|
/// dispatch a `POST` request to `/` with a JSON body:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// use rocket::local::asynchronous::{Client, LocalRequest};
|
/// use rocket::local::asynchronous::{Client, LocalRequest};
|
||||||
/// use rocket::http::{ContentType, Cookie};
|
/// use rocket::http::{ContentType, Cookie};
|
||||||
///
|
///
|
||||||
|
|
|
@ -27,11 +27,10 @@ use crate::{Request, Response};
|
||||||
/// "Hello, world!"
|
/// "Hello, world!"
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # /*
|
|
||||||
/// #[launch]
|
/// #[launch]
|
||||||
/// # */
|
|
||||||
/// fn rocket() -> rocket::Rocket {
|
/// fn rocket() -> rocket::Rocket {
|
||||||
/// rocket::ignite().mount("/", routes![hello_world])
|
/// rocket::ignite().mount("/", routes![hello_world])
|
||||||
|
/// # .reconfigure(rocket::Config::debug_default())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # async fn read_body_manually() -> io::Result<()> {
|
/// # async fn read_body_manually() -> io::Result<()> {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::http::Method;
|
||||||
/// The following snippet creates a `Client` from a `Rocket` instance and
|
/// The following snippet creates a `Client` from a `Rocket` instance and
|
||||||
/// dispatches a local `POST /` request with a body of `Hello, world!`.
|
/// dispatches a local `POST /` request with a body of `Hello, world!`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// use rocket::local::blocking::Client;
|
/// use rocket::local::blocking::Client;
|
||||||
///
|
///
|
||||||
/// let rocket = rocket::ignite();
|
/// let rocket = rocket::ignite();
|
||||||
|
@ -47,8 +47,7 @@ impl Client {
|
||||||
pub fn _test<T, F>(f: F) -> T
|
pub fn _test<T, F>(f: F) -> T
|
||||||
where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send
|
where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send
|
||||||
{
|
{
|
||||||
let rocket = crate::ignite();
|
let client = Client::debug(crate::ignite()).unwrap();
|
||||||
let client = Client::untracked(rocket).expect("valid rocket");
|
|
||||||
let request = client.get("/");
|
let request = client.get("/");
|
||||||
let response = request.clone().dispatch();
|
let response = request.clone().dispatch();
|
||||||
f(&client, request, response)
|
f(&client, request, response)
|
||||||
|
@ -93,6 +92,12 @@ impl Client {
|
||||||
pub_client_impl!("use rocket::local::blocking::Client;");
|
pub_client_impl!("use rocket::local::blocking::Client;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Client {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self._rocket().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for Client {
|
impl Drop for Client {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let client = self.inner.take();
|
let client = self.inner.take();
|
||||||
|
|
|
@ -13,7 +13,7 @@ use super::{Client, LocalResponse};
|
||||||
/// The following snippet uses the available builder methods to construct and
|
/// The following snippet uses the available builder methods to construct and
|
||||||
/// dispatch a `POST` request to `/` with a JSON body:
|
/// dispatch a `POST` request to `/` with a JSON body:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// use rocket::local::blocking::{Client, LocalRequest};
|
/// use rocket::local::blocking::{Client, LocalRequest};
|
||||||
/// use rocket::http::{ContentType, Cookie};
|
/// use rocket::http::{ContentType, Cookie};
|
||||||
///
|
///
|
||||||
|
|
|
@ -24,11 +24,10 @@ use super::Client;
|
||||||
/// "Hello, world!"
|
/// "Hello, world!"
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # /*
|
|
||||||
/// #[launch]
|
/// #[launch]
|
||||||
/// # */
|
|
||||||
/// fn rocket() -> rocket::Rocket {
|
/// fn rocket() -> rocket::Rocket {
|
||||||
/// rocket::ignite().mount("/", routes![hello_world])
|
/// rocket::ignite().mount("/", routes![hello_world])
|
||||||
|
/// # .reconfigure(rocket::Config::debug_default())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # fn read_body_manually() -> io::Result<()> {
|
/// # fn read_body_manually() -> io::Result<()> {
|
||||||
|
|
|
@ -96,11 +96,17 @@ macro_rules! pub_client_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub $($prefix)? fn debug(base: &str, routes: Vec<crate::Route>) -> Result<Self, Error> {
|
pub $($prefix)? fn debug_with(routes: Vec<crate::Route>) -> Result<Self, Error> {
|
||||||
let mut config = crate::Config::debug_default();
|
let rocket = crate::custom(crate::Config::debug_default());
|
||||||
|
Self::debug(rocket.mount("/", routes)) $(.$suffix)?
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub $($prefix)? fn debug(rocket: Rocket) -> Result<Self, Error> {
|
||||||
|
let mut config = rocket.config().clone();
|
||||||
config.log_level = crate::config::LogLevel::Debug;
|
config.log_level = crate::config::LogLevel::Debug;
|
||||||
let rocket = crate::custom(config).mount(base, routes);
|
config.profile = crate::Config::DEBUG_PROFILE;
|
||||||
Self::tracked(rocket) $(.$suffix)?
|
Self::tracked(rocket.reconfigure(config)) $(.$suffix)?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated alias to [`Client::tracked()`].
|
/// Deprecated alias to [`Client::tracked()`].
|
||||||
|
@ -117,7 +123,7 @@ macro_rules! pub_client_impl {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```rust
|
||||||
#[doc = $import]
|
#[doc = $import]
|
||||||
///
|
///
|
||||||
/// # Client::_test(|client, _, _| {
|
/// # Client::_test(|client, _, _| {
|
||||||
|
@ -196,5 +202,8 @@ macro_rules! pub_client_impl {
|
||||||
fn _ensure_impls_exist() {
|
fn _ensure_impls_exist() {
|
||||||
fn is_send<T: Send>() {}
|
fn is_send<T: Send>() {}
|
||||||
is_send::<Self>();
|
is_send::<Self>();
|
||||||
|
|
||||||
|
fn is_debug<T: std::fmt::Debug>() {}
|
||||||
|
is_debug::<Self>();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -163,27 +163,25 @@ impl log::Log for RocketLogger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_init(level: LogLevel, colors: bool, verbose: bool) -> bool {
|
pub(crate) fn init(config: &crate::Config) -> bool {
|
||||||
if level == LogLevel::Off {
|
if config.log_level == LogLevel::Off {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !atty::is(atty::Stream::Stdout)
|
if !atty::is(atty::Stream::Stdout)
|
||||||
|| (cfg!(windows) && !Paint::enable_windows_ascii())
|
|| (cfg!(windows) && !Paint::enable_windows_ascii())
|
||||||
|| !colors
|
|| !config.cli_colors
|
||||||
{
|
{
|
||||||
Paint::disable();
|
Paint::disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = log::set_boxed_logger(Box::new(RocketLogger(level))) {
|
if let Err(e) = log::set_boxed_logger(Box::new(RocketLogger(config.log_level))) {
|
||||||
if verbose {
|
if config.log_level == LogLevel::Debug {
|
||||||
eprintln!("Logger failed to initialize: {}", e);
|
eprintln!("Logger failed to initialize: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log::set_max_level(level.to_level_filter());
|
log::set_max_level(config.log_level.to_level_filter());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +197,6 @@ impl PaintExt for Paint<&str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn init(level: LogLevel) -> bool {
|
|
||||||
try_init(level, true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose logging macros as (hidden) funcions for use by core/contrib codegen.
|
// Expose logging macros as (hidden) funcions for use by core/contrib codegen.
|
||||||
macro_rules! external_log_function {
|
macro_rules! external_log_function {
|
||||||
($fn_name:ident: $macro_name:ident) => (
|
($fn_name:ident: $macro_name:ident) => (
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::Method;
|
/// use rocket::http::Method;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// # let post = |uri| c.post(uri);
|
/// # let post = |uri| c.post(uri);
|
||||||
/// assert_eq!(get("/").method(), Method::Get);
|
/// assert_eq!(get("/").method(), Method::Get);
|
||||||
|
@ -139,7 +139,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert_eq!(get("/hello/rocketeer").uri().path(), "/hello/rocketeer");
|
/// assert_eq!(get("/hello/rocketeer").uri().path(), "/hello/rocketeer");
|
||||||
/// assert_eq!(get("/hello").uri().query(), None);
|
/// assert_eq!(get("/hello").uri().query(), None);
|
||||||
|
@ -231,7 +231,7 @@ impl<'r> Request<'r> {
|
||||||
/// use std::net::Ipv4Addr;
|
/// use std::net::Ipv4Addr;
|
||||||
/// use rocket::http::Header;
|
/// use rocket::http::Header;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let req = c.get("/");
|
/// # let req = c.get("/");
|
||||||
/// assert_eq!(req.real_ip(), None);
|
/// assert_eq!(req.real_ip(), None);
|
||||||
///
|
///
|
||||||
|
@ -292,7 +292,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::Cookie;
|
/// use rocket::http::Cookie;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// # let req = request.inner();
|
/// # let req = request.inner();
|
||||||
/// req.cookies().add(Cookie::new("key", "val"));
|
/// req.cookies().add(Cookie::new("key", "val"));
|
||||||
|
@ -312,7 +312,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::{Accept, ContentType};
|
/// use rocket::http::{Accept, ContentType};
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert!(get("/").headers().is_empty());
|
/// assert!(get("/").headers().is_empty());
|
||||||
///
|
///
|
||||||
|
@ -384,7 +384,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::ContentType;
|
/// use rocket::http::ContentType;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert_eq!(get("/").content_type(), None);
|
/// assert_eq!(get("/").content_type(), None);
|
||||||
///
|
///
|
||||||
|
@ -406,7 +406,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::Accept;
|
/// use rocket::http::Accept;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert_eq!(get("/").accept(), None);
|
/// assert_eq!(get("/").accept(), None);
|
||||||
/// assert_eq!(get("/").header(Accept::JSON).accept(), Some(&Accept::JSON));
|
/// assert_eq!(get("/").header(Accept::JSON).accept(), Some(&Accept::JSON));
|
||||||
|
@ -432,7 +432,7 @@ impl<'r> Request<'r> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::{Accept, ContentType, MediaType};
|
/// use rocket::http::{Accept, ContentType, MediaType};
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// # let post = |uri| c.post(uri);
|
/// # let post = |uri| c.post(uri);
|
||||||
///
|
///
|
||||||
|
@ -472,7 +472,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// let config = request.config();
|
/// let config = request.config();
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -486,7 +486,7 @@ impl<'r> Request<'r> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::data::ToByteUnit;
|
/// use rocket::data::ToByteUnit;
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
///
|
///
|
||||||
/// // This is the default `form` limit.
|
/// // This is the default `form` limit.
|
||||||
|
@ -508,7 +508,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// let route = request.route();
|
/// let route = request.route();
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -525,7 +525,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # type User = rocket::http::Method;
|
/// # type User = rocket::http::Method;
|
||||||
/// # rocket::async_test(async move {
|
/// # rocket::async_test(async move {
|
||||||
/// # let c = rocket::local::asynchronous::Client::debug("/", vec![]).await.unwrap();
|
/// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// let outcome = request.guard::<User>().await;
|
/// let outcome = request.guard::<User>().await;
|
||||||
/// # })
|
/// # })
|
||||||
|
@ -541,7 +541,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// # type Pool = usize;
|
/// # type Pool = usize;
|
||||||
/// let pool = request.managed_state::<Pool>();
|
/// let pool = request.managed_state::<Pool>();
|
||||||
|
@ -567,7 +567,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// // The first store into local cache for a given type wins.
|
/// // The first store into local cache for a given type wins.
|
||||||
/// let value = request.local_cache(|| "hello");
|
/// let value = request.local_cache(|| "hello");
|
||||||
|
@ -602,7 +602,7 @@ impl<'r> Request<'r> {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # rocket::async_test(async move {
|
/// # rocket::async_test(async move {
|
||||||
/// # let c = rocket::local::asynchronous::Client::debug("/", vec![]).await.unwrap();
|
/// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap();
|
||||||
/// # let request = c.get("/");
|
/// # let request = c.get("/");
|
||||||
/// let current_user = request.local_cache_async(async {
|
/// let current_user = request.local_cache_async(async {
|
||||||
/// current_user(&request).await
|
/// current_user(&request).await
|
||||||
|
@ -636,7 +636,7 @@ impl<'r> Request<'r> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert_eq!(get("/a/b/c").param(0), Some(Ok("a")));
|
/// assert_eq!(get("/a/b/c").param(0), Some(Ok("a")));
|
||||||
/// assert_eq!(get("/a/b/c").param(1), Some(Ok("b")));
|
/// assert_eq!(get("/a/b/c").param(1), Some(Ok("b")));
|
||||||
|
@ -674,7 +674,7 @@ impl<'r> Request<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::path::PathBuf;
|
/// use std::path::PathBuf;
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// assert_eq!(get("/").segments(0..), Ok(PathBuf::new()));
|
/// assert_eq!(get("/").segments(0..), Ok(PathBuf::new()));
|
||||||
/// assert_eq!(get("/").segments(2..), Ok(PathBuf::new()));
|
/// assert_eq!(get("/").segments(2..), Ok(PathBuf::new()));
|
||||||
|
@ -723,7 +723,7 @@ impl<'r> Request<'r> {
|
||||||
/// age: usize
|
/// age: usize
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap();
|
/// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();
|
||||||
/// # let get = |uri| c.get(uri);
|
/// # let get = |uri| c.get(uri);
|
||||||
/// let req = get("/?a=apple&z=zebra&a=aardvark");
|
/// let req = get("/?a=apple&z=zebra&a=aardvark");
|
||||||
/// assert_eq!(req.query_value::<&str>("a").unwrap(), Ok("apple"));
|
/// assert_eq!(req.query_value::<&str>("a").unwrap(), Ok("apple"));
|
||||||
|
|
|
@ -69,8 +69,7 @@ impl<'r, R> Created<R> {
|
||||||
/// status::Created::new("http://myservice.com/resource.json")
|
/// status::Created::new("http://myservice.com/resource.json")
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # let rocket = rocket::ignite().mount("/", routes![create]);
|
/// # let client = Client::debug_with(routes![create]).unwrap();
|
||||||
/// # let client = Client::tracked(rocket).unwrap();
|
|
||||||
/// let response = client.get("/").dispatch();
|
/// let response = client.get("/").dispatch();
|
||||||
///
|
///
|
||||||
/// let loc = response.headers().get_one("Location");
|
/// let loc = response.headers().get_one("Location");
|
||||||
|
@ -98,8 +97,7 @@ impl<'r, R> Created<R> {
|
||||||
/// .body("{ 'resource': 'Hello, world!' }")
|
/// .body("{ 'resource': 'Hello, world!' }")
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # let rocket = rocket::ignite().mount("/", routes![create]);
|
/// # let client = Client::debug_with(routes![create]).unwrap();
|
||||||
/// # let client = Client::tracked(rocket).unwrap();
|
|
||||||
/// let response = client.get("/").dispatch();
|
/// let response = client.get("/").dispatch();
|
||||||
///
|
///
|
||||||
/// let loc = response.headers().get_one("Location");
|
/// let loc = response.headers().get_one("Location");
|
||||||
|
@ -131,8 +129,7 @@ impl<'r, R> Created<R> {
|
||||||
/// .tagged_body("{ 'resource': 'Hello, world!' }")
|
/// .tagged_body("{ 'resource': 'Hello, world!' }")
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # let rocket = rocket::ignite().mount("/", routes![create]);
|
/// # let client = Client::debug_with(routes![create]).unwrap();
|
||||||
/// # let client = Client::tracked(rocket).unwrap();
|
|
||||||
/// let response = client.get("/").dispatch();
|
/// let response = client.get("/").dispatch();
|
||||||
///
|
///
|
||||||
/// let loc = response.headers().get_one("Location");
|
/// let loc = response.headers().get_one("Location");
|
||||||
|
|
|
@ -18,6 +18,7 @@ use crate::error::{Error, ErrorKind};
|
||||||
|
|
||||||
/// The main `Rocket` type: used to mount routes and catchers and launch the
|
/// The main `Rocket` type: used to mount routes and catchers and launch the
|
||||||
/// application.
|
/// application.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Rocket {
|
pub struct Rocket {
|
||||||
pub(crate) config: Config,
|
pub(crate) config: Config,
|
||||||
pub(crate) figment: Figment,
|
pub(crate) figment: Figment,
|
||||||
|
@ -53,6 +54,7 @@ impl Rocket {
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
#[inline(always)]
|
||||||
pub fn ignite() -> Rocket {
|
pub fn ignite() -> Rocket {
|
||||||
Rocket::custom(Config::figment())
|
Rocket::custom(Config::figment())
|
||||||
}
|
}
|
||||||
|
@ -63,10 +65,10 @@ impl Rocket {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If there is an error reading configuration sources, this function prints
|
/// If there is an error reading a [`Config`] from `provider`, function
|
||||||
/// a nice error message and then exits the process.
|
/// prints a nice error message and then exits the process.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use figment::{Figment, providers::{Toml, Env, Format}};
|
/// use figment::{Figment, providers::{Toml, Env, Format}};
|
||||||
|
@ -80,18 +82,17 @@ impl Rocket {
|
||||||
/// rocket::custom(figment)
|
/// rocket::custom(figment)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn custom<T: figment::Provider>(provider: T) -> Rocket {
|
pub fn custom<T: figment::Provider>(provider: T) -> Rocket {
|
||||||
let (config, figment) = (Config::from(&provider), Figment::from(provider));
|
let config = Config::from(&provider);
|
||||||
logger::try_init(config.log_level, config.cli_colors, false);
|
let figment = Figment::from(provider);
|
||||||
|
logger::init(&config);
|
||||||
config.pretty_print(&figment);
|
config.pretty_print(&figment);
|
||||||
|
|
||||||
let managed_state = <Container![Send + Sync]>::new();
|
let managed_state = <Container![Send + Sync]>::new();
|
||||||
let (shutdown_sender, shutdown_receiver) = mpsc::channel(1);
|
let (shutdown_sender, shutdown_receiver) = mpsc::channel(1);
|
||||||
Rocket {
|
Rocket {
|
||||||
config, figment,
|
config, figment, managed_state,
|
||||||
managed_state,
|
|
||||||
shutdown_handle: Shutdown(shutdown_sender),
|
shutdown_handle: Shutdown(shutdown_sender),
|
||||||
router: Router::new(),
|
router: Router::new(),
|
||||||
default_catcher: None,
|
default_catcher: None,
|
||||||
|
@ -101,6 +102,56 @@ impl Rocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resets the configuration in `self` to that provided by `provider`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Like [`Rocket::custom()`], panics if `provider` does not provide a valid
|
||||||
|
/// [`Config`]. The error message is printed.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// To modify only some values, use the existing `config`:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::net::Ipv4Addr;
|
||||||
|
///
|
||||||
|
/// let config = rocket::Config {
|
||||||
|
/// port: 7777,
|
||||||
|
/// address: Ipv4Addr::new(18, 127, 0, 1).into(),
|
||||||
|
/// ..rocket::Config::default()
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// let rocket = rocket::custom(&config);
|
||||||
|
/// assert_eq!(rocket.config().port, 7777);
|
||||||
|
/// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1));
|
||||||
|
///
|
||||||
|
/// // Modifying the existing config:
|
||||||
|
/// let mut new_config = rocket.config().clone();
|
||||||
|
/// new_config.port = 8888;
|
||||||
|
///
|
||||||
|
/// let rocket = rocket.reconfigure(new_config);
|
||||||
|
/// assert_eq!(rocket.config().port, 8888);
|
||||||
|
/// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1));
|
||||||
|
///
|
||||||
|
/// // Modifying the existing figment:
|
||||||
|
/// let mut new_figment = rocket.figment().clone()
|
||||||
|
/// .merge(("address", "171.64.200.10"));
|
||||||
|
///
|
||||||
|
/// let rocket = rocket.reconfigure(new_figment);
|
||||||
|
/// assert_eq!(rocket.config().port, 8888);
|
||||||
|
/// assert_eq!(rocket.config().address, Ipv4Addr::new(171, 64, 200, 10));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn reconfigure<T: figment::Provider>(mut self, provider: T) -> Rocket {
|
||||||
|
self.config = Config::from(&provider);
|
||||||
|
self.figment = Figment::from(provider);
|
||||||
|
logger::init(&self.config);
|
||||||
|
self.config.pretty_print(&self.figment);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Mounts all of the routes in the supplied vector at the given `base`
|
/// Mounts all of the routes in the supplied vector at the given `base`
|
||||||
/// path. Mounting a route with path `path` at path `base` makes the route
|
/// path. Mounting a route with path `path` at path `base` makes the route
|
||||||
/// available at `base/path`.
|
/// available at `base/path`.
|
||||||
|
@ -152,7 +203,6 @@ impl Rocket {
|
||||||
/// # .launch().await;
|
/// # .launch().await;
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
|
||||||
pub fn mount<R: Into<Vec<Route>>>(mut self, base: &str, routes: R) -> Self {
|
pub fn mount<R: Into<Vec<Route>>>(mut self, base: &str, routes: R) -> Self {
|
||||||
let base_uri = Origin::parse_owned(base.to_string())
|
let base_uri = Origin::parse_owned(base.to_string())
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
|
@ -210,7 +260,6 @@ impl Rocket {
|
||||||
/// rocket::ignite().register(catchers![internal_error, not_found])
|
/// rocket::ignite().register(catchers![internal_error, not_found])
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
|
||||||
pub fn register(mut self, catchers: Vec<Catcher>) -> Self {
|
pub fn register(mut self, catchers: Vec<Catcher>) -> Self {
|
||||||
info!("{}{}", Paint::emoji("👾 "), Paint::magenta("Catchers:"));
|
info!("{}{}", Paint::emoji("👾 "), Paint::magenta("Catchers:"));
|
||||||
|
|
||||||
|
@ -294,7 +343,6 @@ impl Rocket {
|
||||||
/// }))
|
/// }))
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
|
||||||
pub fn attach<F: Fairing>(mut self, fairing: F) -> Self {
|
pub fn attach<F: Fairing>(mut self, fairing: F) -> Self {
|
||||||
let future = async move {
|
let future = async move {
|
||||||
let fairing = Box::new(fairing);
|
let fairing = Box::new(fairing);
|
||||||
|
@ -472,8 +520,10 @@ impl Rocket {
|
||||||
self.shutdown_handle.clone()
|
self.shutdown_handle.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform "pre-launch" checks: verify that there are no routing colisions
|
/// Perform "pre-launch" checks: verify:
|
||||||
/// and that there were no fairing failures.
|
/// * there are no routing colisionns
|
||||||
|
/// * there were no fairing failures
|
||||||
|
/// * a secret key, if needed, is securely configured
|
||||||
pub(crate) async fn prelaunch_check(&mut self) -> Result<(), Error> {
|
pub(crate) async fn prelaunch_check(&mut self) -> Result<(), Error> {
|
||||||
if let Err(e) = self.router.collisions() {
|
if let Err(e) = self.router.collisions() {
|
||||||
return Err(Error::new(ErrorKind::Collision(e)));
|
return Err(Error::new(ErrorKind::Collision(e)));
|
||||||
|
@ -483,6 +533,25 @@ impl Rocket {
|
||||||
return Err(Error::new(ErrorKind::FailedFairings(failures.to_vec())))
|
return Err(Error::new(ErrorKind::FailedFairings(failures.to_vec())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "secrets")]
|
||||||
|
if !self.config.secret_key.is_provided() {
|
||||||
|
let profile = self.figment.profile();
|
||||||
|
if profile != Config::DEBUG_PROFILE {
|
||||||
|
return Err(Error::new(ErrorKind::InsecureSecretKey(profile.clone())));
|
||||||
|
} else {
|
||||||
|
self.config.secret_key = crate::config::SecretKey::generate()
|
||||||
|
.unwrap_or(crate::config::SecretKey::zero());
|
||||||
|
|
||||||
|
warn!("secrets enabled without a configured `secret_key`");
|
||||||
|
info_!("disable `secrets` feature or configure a `secret_key`");
|
||||||
|
info_!("this becomes an {} in non-debug profiles", Paint::red("error"));
|
||||||
|
|
||||||
|
if !self.config.secret_key.is_zero() {
|
||||||
|
warn_!("a random key has been generated for this launch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub use self::segment::Segment;
|
||||||
// type Selector = (Method, usize);
|
// type Selector = (Method, usize);
|
||||||
type Selector = Method;
|
type Selector = Method;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Router {
|
pub struct Router {
|
||||||
routes: HashMap<Selector, Vec<Route>>,
|
routes: HashMap<Selector, Vec<Route>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ mod test_absolute_uris_okay {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn redirect_works() {
|
fn redirect_works() {
|
||||||
let client = Client::debug("/", routes![google, redirect]).unwrap();
|
let client = Client::debug_with(routes![google, redirect]).unwrap();
|
||||||
|
|
||||||
let response = client.get("/google").dispatch();
|
let response = client.get("/google").dispatch();
|
||||||
let location = response.headers().get_one("Location");
|
let location = response.headers().get_one("Location");
|
||||||
|
|
|
@ -29,7 +29,7 @@ mod tests {
|
||||||
req.cookies().add(Cookie::new("fairing", "woo"));
|
req.cookies().add(Cookie::new("fairing", "woo"));
|
||||||
})));
|
})));
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
// Check that the index returns the `index` and `fairing` cookie.
|
// Check that the index returns the `index` and `fairing` cookie.
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
|
|
|
@ -19,8 +19,7 @@ mod conditionally_set_server_header {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn do_not_overwrite_server_header() {
|
fn do_not_overwrite_server_header() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![do_not_overwrite, use_default]);
|
let client = Client::debug_with(routes![do_not_overwrite, use_default]).unwrap();
|
||||||
let client = Client::tracked(rocket).unwrap();
|
|
||||||
|
|
||||||
let response = client.get("/do_not_overwrite").dispatch();
|
let response = client.get("/do_not_overwrite").dispatch();
|
||||||
let server = response.headers().get_one("Server");
|
let server = response.headers().get_one("Server");
|
||||||
|
|
|
@ -45,8 +45,7 @@ fn number(params: ThingForm) -> DerivedResponder {
|
||||||
fn test_derive_reexports() {
|
fn test_derive_reexports() {
|
||||||
use rocket::local::blocking::Client;
|
use rocket::local::blocking::Client;
|
||||||
|
|
||||||
let rocket = rocket::ignite().mount("/", routes![index, number]);
|
let client = Client::debug_with(routes![index, number]).unwrap();
|
||||||
let client = Client::tracked(rocket).unwrap();
|
|
||||||
|
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "hello");
|
assert_eq!(response.into_string().unwrap(), "hello");
|
||||||
|
|
|
@ -10,8 +10,7 @@ mod encoded_uris {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_route_to_encoded_uri() {
|
fn can_route_to_encoded_uri() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![super::index]);
|
let client = Client::debug_with(routes![super::index]).unwrap();
|
||||||
let client = Client::untracked(rocket).unwrap();
|
|
||||||
let response = client.get("/hello%20s%C3%BCper%20%24?a&%3F&value=a+b")
|
let response = client.get("/hello%20s%C3%BCper%20%24?a&%3F&value=a+b")
|
||||||
.dispatch()
|
.dispatch()
|
||||||
.into_string();
|
.into_string();
|
||||||
|
|
|
@ -40,7 +40,7 @@ mod fairing_before_head_strip {
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let response = client.head("/").dispatch();
|
let response = client.head("/").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert!(response.body().is_none());
|
assert!(response.body().is_none());
|
||||||
|
@ -71,7 +71,7 @@ mod fairing_before_head_strip {
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let response = client.head("/").dispatch();
|
let response = client.head("/").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert!(response.body().is_none());
|
assert!(response.body().is_none());
|
||||||
|
|
|
@ -27,10 +27,9 @@ mod flash_lazy_remove_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
use super::*;
|
use super::*;
|
||||||
let r = rocket::ignite().mount("/", routes![set, unused, used]);
|
|
||||||
let client = Client::tracked(r).unwrap();
|
|
||||||
|
|
||||||
// Ensure the cookie's not there at first.
|
// Ensure the cookie's not there at first.
|
||||||
|
let client = Client::debug_with(routes![set, unused, used]).unwrap();
|
||||||
let response = client.get("/unused").dispatch();
|
let response = client.get("/unused").dispatch();
|
||||||
assert_eq!(response.status(), Status::NotFound);
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn method_eval() {
|
fn method_eval() {
|
||||||
let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap();
|
let client = Client::debug_with(routes![bug]).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
.body("_method=patch&form_data=Form+data")
|
.body("_method=patch&form_data=Form+data")
|
||||||
|
@ -31,7 +31,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_passes_through() {
|
fn get_passes_through() {
|
||||||
let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap();
|
let client = Client::debug_with(routes![bug]).unwrap();
|
||||||
let response = client.get("/")
|
let response = client.get("/")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
.body("_method=patch&form_data=Form+data")
|
.body("_method=patch&form_data=Form+data")
|
||||||
|
|
|
@ -14,7 +14,7 @@ mod tests {
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
fn check_decoding(raw: &str, decoded: &str) {
|
fn check_decoding(raw: &str, decoded: &str) {
|
||||||
let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap();
|
let client = Client::debug_with(routes![bug]).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
.body(format!("form_data={}", raw))
|
.body(format!("form_data={}", raw))
|
||||||
|
|
|
@ -30,7 +30,7 @@ mod head_handling_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auto_head() {
|
fn auto_head() {
|
||||||
let client = Client::tracked(rocket::ignite().mount("/", routes())).unwrap();
|
let client = Client::debug_with(routes()).unwrap();
|
||||||
let response = client.head("/").dispatch();
|
let response = client.head("/").dispatch();
|
||||||
|
|
||||||
let content_type: Vec<_> = response.headers().get("Content-Type").collect();
|
let content_type: Vec<_> = response.headers().get("Content-Type").collect();
|
||||||
|
@ -46,7 +46,7 @@ mod head_handling_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn user_head() {
|
fn user_head() {
|
||||||
let client = Client::tracked(rocket::ignite().mount("/", routes())).unwrap();
|
let client = Client::debug_with(routes()).unwrap();
|
||||||
let response = client.head("/other").dispatch();
|
let response = client.head("/other").dispatch();
|
||||||
|
|
||||||
let content_type: Vec<_> = response.headers().get("Content-Type").collect();
|
let content_type: Vec<_> = response.headers().get("Content-Type").collect();
|
||||||
|
|
|
@ -14,17 +14,14 @@ mod limits_tests {
|
||||||
use rocket::data::Limits;
|
use rocket::data::Limits;
|
||||||
|
|
||||||
fn rocket_with_forms_limit(limit: u64) -> rocket::Rocket {
|
fn rocket_with_forms_limit(limit: u64) -> rocket::Rocket {
|
||||||
let config = rocket::Config {
|
let mut config = rocket::Config::debug_default();
|
||||||
limits: Limits::default().limit("form", limit.into()),
|
config.limits = Limits::default().limit("form", limit.into());
|
||||||
..rocket::Config::debug_default()
|
|
||||||
};
|
|
||||||
|
|
||||||
rocket::custom(config).mount("/", routes![super::index])
|
rocket::custom(config).mount("/", routes![super::index])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn large_enough() {
|
fn large_enough() {
|
||||||
let client = Client::tracked(rocket_with_forms_limit(128)).unwrap();
|
let client = Client::debug(rocket_with_forms_limit(128)).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.body("value=Hello+world")
|
.body("value=Hello+world")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
|
@ -35,7 +32,7 @@ mod limits_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn just_large_enough() {
|
fn just_large_enough() {
|
||||||
let client = Client::tracked(rocket_with_forms_limit(17)).unwrap();
|
let client = Client::debug(rocket_with_forms_limit(17)).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.body("value=Hello+world")
|
.body("value=Hello+world")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
|
@ -46,7 +43,7 @@ mod limits_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn much_too_small() {
|
fn much_too_small() {
|
||||||
let client = Client::tracked(rocket_with_forms_limit(4)).unwrap();
|
let client = Client::debug(rocket_with_forms_limit(4)).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.body("value=Hello+world")
|
.body("value=Hello+world")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
|
@ -57,7 +54,7 @@ mod limits_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn contracted() {
|
fn contracted() {
|
||||||
let client = Client::tracked(rocket_with_forms_limit(10)).unwrap();
|
let client = Client::debug(rocket_with_forms_limit(10)).unwrap();
|
||||||
let response = client.post("/")
|
let response = client.post("/")
|
||||||
.body("value=Hello+world")
|
.body("value=Hello+world")
|
||||||
.header(ContentType::Form)
|
.header(ContentType::Form)
|
||||||
|
|
|
@ -10,5 +10,5 @@ impl Drop for SpawnBlockingOnDrop {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_access_runtime_in_state_drop() {
|
fn test_access_runtime_in_state_drop() {
|
||||||
Client::tracked(rocket::ignite().manage(SpawnBlockingOnDrop)).unwrap();
|
Client::debug(rocket::ignite().manage(SpawnBlockingOnDrop)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ mod local_request_content_type_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn has_no_ct() {
|
fn has_no_ct() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
|
||||||
let req = client.post("/");
|
let req = client.post("/");
|
||||||
assert_eq!(req.clone().dispatch().into_string(), Some("Absent".to_string()));
|
assert_eq!(req.clone().dispatch().into_string(), Some("Absent".to_string()));
|
||||||
|
@ -69,7 +69,7 @@ mod local_request_content_type_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn has_ct() {
|
fn has_ct() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
|
||||||
let req = client.post("/").header(ContentType::JSON);
|
let req = client.post("/").header(ContentType::JSON);
|
||||||
assert_eq!(req.clone().dispatch().into_string(), Some("Present".to_string()));
|
assert_eq!(req.clone().dispatch().into_string(), Some("Present".to_string()));
|
||||||
|
|
|
@ -20,7 +20,7 @@ mod tests {
|
||||||
fn private_cookie_is_returned() {
|
fn private_cookie_is_returned() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);
|
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let req = client.get("/").private_cookie(Cookie::new("cookie_name", "cookie_value"));
|
let req = client.get("/").private_cookie(Cookie::new("cookie_name", "cookie_value"));
|
||||||
let response = req.dispatch();
|
let response = req.dispatch();
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ mod tests {
|
||||||
fn regular_cookie_is_not_returned() {
|
fn regular_cookie_is_not_returned() {
|
||||||
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);
|
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let req = client.get("/").cookie(Cookie::new("cookie_name", "cookie_value"));
|
let req = client.get("/").cookie(Cookie::new("cookie_name", "cookie_value"));
|
||||||
let response = req.dispatch();
|
let response = req.dispatch();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ mod many_cookie_jars_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutli_add() {
|
fn test_mutli_add() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.post("/").dispatch();
|
let response = client.post("/").dispatch();
|
||||||
let cookies = response.cookies();
|
let cookies = response.cookies();
|
||||||
assert_eq!(cookies.iter().count(), 2);
|
assert_eq!(cookies.iter().count(), 2);
|
||||||
|
@ -38,7 +38,7 @@ mod many_cookie_jars_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutli_get() {
|
fn test_mutli_get() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.get("/")
|
let response = client.get("/")
|
||||||
.cookie(Cookie::new("a", "a_val"))
|
.cookie(Cookie::new("a", "a_val"))
|
||||||
.cookie(Cookie::new("b", "hi!"))
|
.cookie(Cookie::new("b", "hi!"))
|
||||||
|
|
|
@ -30,7 +30,7 @@ mod mapped_base_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn only_prefix() {
|
fn only_prefix() {
|
||||||
let client = Client::tracked(super::rocket()).unwrap();
|
let client = Client::debug(super::rocket()).unwrap();
|
||||||
|
|
||||||
let response = client.get("/a/b/3").dispatch();
|
let response = client.get("/a/b/3").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "3");
|
assert_eq!(response.into_string().unwrap(), "3");
|
||||||
|
@ -44,7 +44,7 @@ mod mapped_base_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prefix_and_base() {
|
fn prefix_and_base() {
|
||||||
let client = Client::tracked(super::rocket()).unwrap();
|
let client = Client::debug(super::rocket()).unwrap();
|
||||||
|
|
||||||
let response = client.get("/foo/a/b/23").dispatch();
|
let response = client.get("/foo/a/b/23").dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "23");
|
assert_eq!(response.into_string().unwrap(), "23");
|
||||||
|
|
|
@ -46,7 +46,7 @@ mod nested_fairing_attaches_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_counts() {
|
fn test_counts() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
assert_eq!(response.into_string(), Some("1, 1".into()));
|
assert_eq!(response.into_string(), Some("1, 1".into()));
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rocket::futures::channel::oneshot;
|
||||||
#[rocket::async_test]
|
#[rocket::async_test]
|
||||||
async fn on_launch_fairing_can_inspect_port() {
|
async fn on_launch_fairing_can_inspect_port() {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let rocket = rocket::custom(Config { port: 0, ..Default::default() })
|
let rocket = rocket::custom(Config { port: 0, ..Config::debug_default() })
|
||||||
.attach(AdHoc::on_launch("Send Port -> Channel", move |rocket| {
|
.attach(AdHoc::on_launch("Send Port -> Channel", move |rocket| {
|
||||||
tx.send(rocket.config().port).unwrap();
|
tx.send(rocket.config().port).unwrap();
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -32,7 +32,7 @@ fn rocket() -> Rocket {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn catches_route_panic() {
|
fn catches_route_panic() {
|
||||||
let client = Client::untracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.get("/panic").dispatch();
|
let response = client.get("/panic").dispatch();
|
||||||
assert_eq!(response.status(), Status::InternalServerError);
|
assert_eq!(response.status(), Status::InternalServerError);
|
||||||
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
||||||
|
@ -40,7 +40,7 @@ fn catches_route_panic() {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn catches_catcher_panic() {
|
fn catches_catcher_panic() {
|
||||||
let client = Client::untracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.get("/noroute").dispatch();
|
let response = client.get("/noroute").dispatch();
|
||||||
assert_eq!(response.status(), Status::InternalServerError);
|
assert_eq!(response.status(), Status::InternalServerError);
|
||||||
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
assert_eq!(response.into_string().unwrap(), "Hey, sorry! :(");
|
||||||
|
@ -49,7 +49,7 @@ fn catches_catcher_panic() {
|
||||||
#[test]
|
#[test]
|
||||||
fn catches_double_panic() {
|
fn catches_double_panic() {
|
||||||
let rocket = rocket().register(catchers![double_panic]);
|
let rocket = rocket().register(catchers![double_panic]);
|
||||||
let client = Client::untracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
let response = client.get("/noroute").dispatch();
|
let response = client.get("/noroute").dispatch();
|
||||||
assert_eq!(response.status(), Status::InternalServerError);
|
assert_eq!(response.status(), Status::InternalServerError);
|
||||||
assert!(!response.into_string().unwrap().contains(":("));
|
assert!(!response.into_string().unwrap().contains(":("));
|
||||||
|
|
|
@ -35,7 +35,7 @@ mod tests {
|
||||||
|
|
||||||
macro_rules! check_dispatch {
|
macro_rules! check_dispatch {
|
||||||
($mount:expr, $ct:expr, $body:expr) => (
|
($mount:expr, $ct:expr, $body:expr) => (
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let mut req = client.post($mount);
|
let mut req = client.post($mount);
|
||||||
let ct: Option<ContentType> = $ct;
|
let ct: Option<ContentType> = $ct;
|
||||||
if let Some(ct) = ct {
|
if let Some(ct) = ct {
|
||||||
|
|
|
@ -14,7 +14,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_catcher_redirect() {
|
fn error_catcher_redirect() {
|
||||||
let client = Client::tracked(rocket::ignite().register(catchers![not_found])).unwrap();
|
let client = Client::debug(rocket::ignite().register(catchers![not_found])).unwrap();
|
||||||
let response = client.get("/unknown").dispatch();
|
let response = client.get("/unknown").dispatch();
|
||||||
|
|
||||||
let location: Vec<_> = response.headers().get("location").collect();
|
let location: Vec<_> = response.headers().get("location").collect();
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn rocket() -> rocket::Rocket {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_fairing_changes_content_type() {
|
fn check_fairing_changes_content_type() {
|
||||||
let client = Client::untracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let response = client.post("/").header(ContentType::PNG).dispatch();
|
let response = client.post("/").header(ContentType::PNG).dispatch();
|
||||||
assert_eq!(response.into_string().unwrap(), "other");
|
assert_eq!(response.into_string().unwrap(), "other");
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ mod route_guard_tests {
|
||||||
.mount("/first", routes![files])
|
.mount("/first", routes![files])
|
||||||
.mount("/second", routes![files]);
|
.mount("/second", routes![files]);
|
||||||
|
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
assert_path(&client, "/first/some/path");
|
assert_path(&client, "/first/some/path");
|
||||||
assert_path(&client, "/second/some/path");
|
assert_path(&client, "/second/some/path");
|
||||||
assert_path(&client, "/first/second/b/c");
|
assert_path(&client, "/first/second/b/c");
|
||||||
|
|
|
@ -36,7 +36,7 @@ mod tests {
|
||||||
let rocket = rocket::ignite()
|
let rocket = rocket::ignite()
|
||||||
.mount("/", routes![test, two, one_two, none, dual])
|
.mount("/", routes![test, two, one_two, none, dual])
|
||||||
.mount("/point", routes![test, two, one_two, dual]);
|
.mount("/point", routes![test, two, one_two, dual]);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
// We construct a path that matches each of the routes above. We ensure the
|
// We construct a path that matches each of the routes above. We ensure the
|
||||||
// prefix is stripped, confirming that dynamic segments are working.
|
// prefix is stripped, confirming that dynamic segments are working.
|
||||||
|
|
|
@ -15,7 +15,7 @@ mod test_session_cookies {
|
||||||
#[test]
|
#[test]
|
||||||
fn session_cookie_is_session() {
|
fn session_cookie_is_session() {
|
||||||
let rocket = rocket::ignite().mount("/", rocket::routes![index]);
|
let rocket = rocket::ignite().mount("/", rocket::routes![index]);
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::debug(rocket).unwrap();
|
||||||
|
|
||||||
let response = client.get("/").dispatch();
|
let response = client.get("/").dispatch();
|
||||||
let cookie = response.cookies().get_private("key").unwrap();
|
let cookie = response.cookies().get_private("key").unwrap();
|
||||||
|
|
|
@ -25,7 +25,7 @@ mod strict_and_lenient_forms_tests {
|
||||||
const FIELD_VALUE: &str = "just_some_value";
|
const FIELD_VALUE: &str = "just_some_value";
|
||||||
|
|
||||||
fn client() -> Client {
|
fn client() -> Client {
|
||||||
Client::tracked(rocket::ignite().mount("/", routes![strict, lenient])).unwrap()
|
Client::debug_with(routes![strict, lenient]).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rocket::local::blocking::Client;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_local_request_clone_soundness() {
|
fn test_local_request_clone_soundness() {
|
||||||
let client = Client::tracked(rocket::ignite()).unwrap();
|
let client = Client::debug_with(vec![]).unwrap();
|
||||||
|
|
||||||
// creates two LocalRequest instances that shouldn't share the same req
|
// creates two LocalRequest instances that shouldn't share the same req
|
||||||
let r1 = client.get("/").header(Header::new("key", "val1"));
|
let r1 = client.get("/").header(Header::new("key", "val1"));
|
||||||
|
|
|
@ -19,7 +19,8 @@ mod many_cookie_jars_tests {
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
fn rocket() -> rocket::Rocket {
|
fn rocket() -> rocket::Rocket {
|
||||||
rocket::ignite().mount("/", routes![add, get])
|
rocket::custom(rocket::Config::debug_default())
|
||||||
|
.mount("/", routes![add, get])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -33,7 +33,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn uri_percent_encoding_redirect() {
|
fn uri_percent_encoding_redirect() {
|
||||||
let expected_location = vec!["/hello/John%5B%5D%7C%5C%25@%5E"];
|
let expected_location = vec!["/hello/John%5B%5D%7C%5C%25@%5E"];
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
|
||||||
let response = client.get("/raw").dispatch();
|
let response = client.get("/raw").dispatch();
|
||||||
let location: Vec<_> = response.headers().get("location").collect();
|
let location: Vec<_> = response.headers().get("location").collect();
|
||||||
|
@ -48,7 +48,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uri_percent_encoding_get() {
|
fn uri_percent_encoding_get() {
|
||||||
let client = Client::tracked(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let name = Uri::percent_encode(NAME);
|
let name = Uri::percent_encode(NAME);
|
||||||
let response = client.get(format!("/hello/{}", name)).dispatch();
|
let response = client.get(format!("/hello/{}", name)).dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
|
|
@ -47,6 +47,7 @@ CORE_CODEGEN_ROOT=$(relative "core/codegen") || exit $?
|
||||||
CORE_HTTP_ROOT=$(relative "core/http") || exit $?
|
CORE_HTTP_ROOT=$(relative "core/http") || exit $?
|
||||||
CONTRIB_LIB_ROOT=$(relative "contrib/lib") || exit $?
|
CONTRIB_LIB_ROOT=$(relative "contrib/lib") || exit $?
|
||||||
CONTRIB_CODEGEN_ROOT=$(relative "contrib/codegen") || exit $?
|
CONTRIB_CODEGEN_ROOT=$(relative "contrib/codegen") || exit $?
|
||||||
|
GUIDE_TESTS_ROOT=$(relative "site/tests") || exit $?
|
||||||
|
|
||||||
# Root of infrastructure directories.
|
# Root of infrastructure directories.
|
||||||
EXAMPLES_DIR=$(relative "examples") || exit $?
|
EXAMPLES_DIR=$(relative "examples") || exit $?
|
||||||
|
@ -97,6 +98,7 @@ function print_environment() {
|
||||||
echo " CORE_HTTP_ROOT: ${CORE_HTTP_ROOT}"
|
echo " CORE_HTTP_ROOT: ${CORE_HTTP_ROOT}"
|
||||||
echo " CONTRIB_LIB_ROOT: ${CONTRIB_LIB_ROOT}"
|
echo " CONTRIB_LIB_ROOT: ${CONTRIB_LIB_ROOT}"
|
||||||
echo " CONTRIB_CODEGEN_ROOT: ${CONTRIB_CODEGEN_ROOT}"
|
echo " CONTRIB_CODEGEN_ROOT: ${CONTRIB_CODEGEN_ROOT}"
|
||||||
|
echo " GUIDE_TESTS_ROOT: ${GUIDE_TESTS_ROOT}"
|
||||||
echo " EXAMPLES_DIR: ${EXAMPLES_DIR}"
|
echo " EXAMPLES_DIR: ${EXAMPLES_DIR}"
|
||||||
echo " DOC_DIR: ${DOC_DIR}"
|
echo " DOC_DIR: ${DOC_DIR}"
|
||||||
echo " ALL_PROJECT_DIRS: ${ALL_PROJECT_DIRS[*]}"
|
echo " ALL_PROJECT_DIRS: ${ALL_PROJECT_DIRS[*]}"
|
||||||
|
|
|
@ -23,11 +23,10 @@ if ! [ -z "$(git status --porcelain)" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure everything passes before trying to publish.
|
# Ensure everything passes before trying to publish.
|
||||||
echo ":::: Running test suite..."
|
echo ":::: Running complete test suite..."
|
||||||
cargo clean
|
cargo clean
|
||||||
bash "${SCRIPT_DIR}/test.sh"
|
bash "${SCRIPT_DIR}/test.sh" --all
|
||||||
bash "${SCRIPT_DIR}/test.sh" --contrib
|
bash "${SCRIPT_DIR}/test.sh" --all --release
|
||||||
bash "${SCRIPT_DIR}/test.sh" --release
|
|
||||||
|
|
||||||
# Temporarily remove dev-dependencies so crates.io verifies.
|
# Temporarily remove dev-dependencies so crates.io verifies.
|
||||||
echo ":::: Stripping [dev-dependencies]..."
|
echo ":::: Stripping [dev-dependencies]..."
|
||||||
|
|
154
scripts/test.sh
154
scripts/test.sh
|
@ -10,9 +10,6 @@ export PATH=${HOME}/.cargo/bin:${PATH}
|
||||||
export CARGO_INCREMENTAL=0
|
export CARGO_INCREMENTAL=0
|
||||||
CARGO="cargo"
|
CARGO="cargo"
|
||||||
|
|
||||||
# We set a `cfg` so that a missing `secret_key` doesn't abort tests.
|
|
||||||
export RUSTFLAGS="--cfg rocket_unsafe_secret_key"
|
|
||||||
|
|
||||||
# Checks that the versions for Cargo projects $@ all match
|
# Checks that the versions for Cargo projects $@ all match
|
||||||
function check_versions_match() {
|
function check_versions_match() {
|
||||||
local last_version=""
|
local last_version=""
|
||||||
|
@ -54,40 +51,7 @@ function ensure_trailing_whitespace_free() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $1 == +* ]]; then
|
function test_contrib() {
|
||||||
CARGO="$CARGO $1"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The kind of test we'll be running.
|
|
||||||
TEST_KIND="all"
|
|
||||||
|
|
||||||
if [[ "$1" == "--contrib" ]] || [[ "$1" == "--core" ]]; then
|
|
||||||
TEST_KIND=${1#"--"}
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ":: Preparing. Environment is..."
|
|
||||||
print_environment
|
|
||||||
echo " CARGO: $CARGO"
|
|
||||||
echo " RUSTFLAGS: $RUSTFLAGS"
|
|
||||||
echo " EXTRA FLAGS: $@"
|
|
||||||
|
|
||||||
echo ":: Ensuring all crate versions match..."
|
|
||||||
check_versions_match "${ALL_PROJECT_DIRS[@]}"
|
|
||||||
|
|
||||||
echo ":: Checking for tabs..."
|
|
||||||
ensure_tab_free
|
|
||||||
|
|
||||||
echo ":: Checking for trailing whitespace..."
|
|
||||||
ensure_trailing_whitespace_free
|
|
||||||
|
|
||||||
echo ":: Updating dependencies..."
|
|
||||||
if ! $CARGO update ; then
|
|
||||||
echo " WARNING: Update failed! Proceeding with possibly outdated deps..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $TEST_KIND = "contrib" ]; then
|
|
||||||
FEATURES=(
|
FEATURES=(
|
||||||
json
|
json
|
||||||
msgpack
|
msgpack
|
||||||
|
@ -106,18 +70,21 @@ if [ $TEST_KIND = "contrib" ]; then
|
||||||
gzip_compression
|
gzip_compression
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo ":: Building and testing contrib [default]..."
|
||||||
|
|
||||||
pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1
|
pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1
|
||||||
|
|
||||||
echo ":: Building and testing contrib [default]..."
|
$CARGO test $@
|
||||||
$CARGO test $@
|
|
||||||
|
|
||||||
for feature in "${FEATURES[@]}"; do
|
for feature in "${FEATURES[@]}"; do
|
||||||
echo ":: Building and testing contrib [${feature}]..."
|
echo ":: Building and testing contrib [${feature}]..."
|
||||||
$CARGO test --no-default-features --features "${feature}" $@
|
$CARGO test --no-default-features --features "${feature}" $@
|
||||||
done
|
done
|
||||||
|
|
||||||
popd > /dev/null 2>&1
|
popd > /dev/null 2>&1
|
||||||
elif [ $TEST_KIND = "core" ]; then
|
}
|
||||||
|
|
||||||
|
function test_core() {
|
||||||
FEATURES=(
|
FEATURES=(
|
||||||
secrets
|
secrets
|
||||||
tls
|
tls
|
||||||
|
@ -125,16 +92,97 @@ elif [ $TEST_KIND = "core" ]; then
|
||||||
|
|
||||||
pushd "${CORE_LIB_ROOT}" > /dev/null 2>&1
|
pushd "${CORE_LIB_ROOT}" > /dev/null 2>&1
|
||||||
|
|
||||||
echo ":: Building and testing core [no features]..."
|
echo ":: Building and testing core [no features]..."
|
||||||
$CARGO test --no-default-features $@
|
$CARGO test --no-default-features $@
|
||||||
|
|
||||||
for feature in "${FEATURES[@]}"; do
|
for feature in "${FEATURES[@]}"; do
|
||||||
echo ":: Building and testing core [${feature}]..."
|
echo ":: Building and testing core [${feature}]..."
|
||||||
$CARGO test --no-default-features --features "${feature}" $@
|
$CARGO test --no-default-features --features "${feature}" $@
|
||||||
done
|
done
|
||||||
|
|
||||||
popd > /dev/null 2>&1
|
popd > /dev/null 2>&1
|
||||||
else
|
}
|
||||||
echo ":: Building and testing libraries..."
|
|
||||||
$CARGO test --all-features --all $@
|
function test_examples() {
|
||||||
|
for dir in $(find "${EXAMPLES_DIR}" -maxdepth 1 -mindepth 1 -type d); do
|
||||||
|
echo ":: Building and testing example [${dir#"${EXAMPLES_DIR}/"}]..."
|
||||||
|
|
||||||
|
pushd "${dir}" > /dev/null 2>&1
|
||||||
|
$CARGO test $@
|
||||||
|
popd > /dev/null 2>&1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_guide() {
|
||||||
|
echo ":: Building and testing guide..."
|
||||||
|
|
||||||
|
pushd "${GUIDE_TESTS_ROOT}" > /dev/null 2>&1
|
||||||
|
$CARGO test $@
|
||||||
|
popd > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_default() {
|
||||||
|
for project in "${ALL_PROJECT_DIRS[@]}"; do
|
||||||
|
echo ":: Building and testing ${project#"${PROJECT_ROOT}/"}..."
|
||||||
|
|
||||||
|
pushd "${project}" > /dev/null 2>&1
|
||||||
|
$CARGO test --all-features $@
|
||||||
|
popd > /dev/null 2>&1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $1 == +* ]]; then
|
||||||
|
CARGO="$CARGO $1"
|
||||||
|
shift
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# The kind of test we'll be running.
|
||||||
|
TEST_KIND="default"
|
||||||
|
KINDS=("contrib" "core" "examples" "guide" "all")
|
||||||
|
|
||||||
|
if [[ " ${KINDS[@]} " =~ " ${1#"--"} " ]]; then
|
||||||
|
TEST_KIND=${1#"--"}
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ":: Preparing. Environment is..."
|
||||||
|
print_environment
|
||||||
|
echo " CARGO: $CARGO"
|
||||||
|
echo " EXTRA FLAGS: $@"
|
||||||
|
|
||||||
|
echo ":: Ensuring all crate versions match..."
|
||||||
|
check_versions_match "${ALL_PROJECT_DIRS[@]}"
|
||||||
|
|
||||||
|
echo ":: Checking for tabs..."
|
||||||
|
ensure_tab_free
|
||||||
|
|
||||||
|
echo ":: Checking for trailing whitespace..."
|
||||||
|
ensure_trailing_whitespace_free
|
||||||
|
|
||||||
|
echo ":: Updating dependencies..."
|
||||||
|
if ! $CARGO update ; then
|
||||||
|
echo " WARNING: Update failed! Proceeding with possibly outdated deps..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $TEST_KIND in
|
||||||
|
contrib) test_contrib $@ ;;
|
||||||
|
core) test_core $@ ;;
|
||||||
|
examples) test_examples $@ ;;
|
||||||
|
guide) test_guide $@ ;;
|
||||||
|
default)
|
||||||
|
test_examples $@ & examples=$!
|
||||||
|
test_default $@ & default=$!
|
||||||
|
test_guide $@ & guide=$!
|
||||||
|
|
||||||
|
wait $examples && wait $default && wait $guide
|
||||||
|
;;
|
||||||
|
all)
|
||||||
|
test_core $@ & core=$!
|
||||||
|
test_contrib $@ & contrib=$!
|
||||||
|
test_examples $@ & examples=$!
|
||||||
|
test_default $@ & default=$!
|
||||||
|
test_guide $@ & guide=$!
|
||||||
|
|
||||||
|
wait $core && wait $contrib && wait $examples && wait $default && wait $guide
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
|
@ -14,14 +14,14 @@ instance. Usage is straightforward:
|
||||||
|
|
||||||
1. Construct a `Rocket` instance that represents the application.
|
1. Construct a `Rocket` instance that represents the application.
|
||||||
|
|
||||||
```rust
|
```rust,no_run
|
||||||
let rocket = rocket::ignite();
|
let rocket = rocket::ignite();
|
||||||
# let _ = rocket;
|
# let _ = rocket;
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Construct a `Client` using the `Rocket` instance.
|
2. Construct a `Client` using the `Rocket` instance.
|
||||||
|
|
||||||
```rust
|
```rust,no_run
|
||||||
# use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
# let rocket = rocket::ignite();
|
# let rocket = rocket::ignite();
|
||||||
let client = Client::tracked(rocket).unwrap();
|
let client = Client::tracked(rocket).unwrap();
|
||||||
|
@ -30,7 +30,7 @@ instance. Usage is straightforward:
|
||||||
|
|
||||||
3. Construct requests using the `Client` instance.
|
3. Construct requests using the `Client` instance.
|
||||||
|
|
||||||
```rust
|
```rust,no_run
|
||||||
# use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
# let rocket = rocket::ignite();
|
# let rocket = rocket::ignite();
|
||||||
# let client = Client::tracked(rocket).unwrap();
|
# let client = Client::tracked(rocket).unwrap();
|
||||||
|
@ -40,7 +40,7 @@ instance. Usage is straightforward:
|
||||||
|
|
||||||
4. Dispatch the request to retrieve the response.
|
4. Dispatch the request to retrieve the response.
|
||||||
|
|
||||||
```rust
|
```rust,no_run
|
||||||
# use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
# let rocket = rocket::ignite();
|
# let rocket = rocket::ignite();
|
||||||
# let client = Client::tracked(rocket).unwrap();
|
# let client = Client::tracked(rocket).unwrap();
|
||||||
|
@ -97,11 +97,11 @@ These methods are typically used in combination with the `assert_eq!` or
|
||||||
# .finalize()
|
# .finalize()
|
||||||
# }
|
# }
|
||||||
|
|
||||||
use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
|
|
||||||
let rocket = rocket::ignite().mount("/", routes![hello]);
|
# let rocket = rocket::ignite().mount("/", routes![hello]);
|
||||||
let client = Client::tracked(rocket).expect("valid rocket instance");
|
# let client = Client::debug(rocket).expect("valid rocket instance");
|
||||||
let mut response = client.get("/").dispatch();
|
let mut response = client.get("/").dispatch();
|
||||||
|
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
@ -165,7 +165,9 @@ To test our "Hello, world!" application, we create a `Client` for our
|
||||||
testing: we _want_ our tests to panic when something goes wrong.
|
testing: we _want_ our tests to panic when something goes wrong.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# fn rocket() -> rocket::Rocket { rocket::ignite() }
|
# fn rocket() -> rocket::Rocket {
|
||||||
|
# rocket::ignite().reconfigure(rocket::Config::debug_default())
|
||||||
|
# }
|
||||||
# use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
|
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
||||||
|
@ -175,7 +177,9 @@ Then, we create a new `GET /` request and dispatch it, getting back our
|
||||||
application's response:
|
application's response:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# fn rocket() -> rocket::Rocket { rocket::ignite() }
|
# fn rocket() -> rocket::Rocket {
|
||||||
|
# rocket::ignite().reconfigure(rocket::Config::debug_default())
|
||||||
|
# }
|
||||||
# use rocket::local::blocking::Client;
|
# use rocket::local::blocking::Client;
|
||||||
# let client = Client::tracked(rocket()).expect("valid rocket instance");
|
# let client = Client::tracked(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client.get("/").dispatch();
|
let mut response = client.get("/").dispatch();
|
||||||
|
@ -199,7 +203,7 @@ We do this by checking the `Response` object directly:
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
#
|
#
|
||||||
# let rocket = rocket::ignite().mount("/", routes![hello]);
|
# let rocket = rocket::ignite().mount("/", routes![hello]);
|
||||||
# let client = Client::tracked(rocket).expect("valid rocket instance");
|
# let client = Client::debug(rocket).expect("valid rocket instance");
|
||||||
# let mut response = client.get("/").dispatch();
|
# let mut response = client.get("/").dispatch();
|
||||||
|
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
@ -232,7 +236,10 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
# */ pub
|
# */ pub
|
||||||
fn hello_world() {
|
fn hello_world() {
|
||||||
|
# /*
|
||||||
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
let client = Client::tracked(rocket()).expect("valid rocket instance");
|
||||||
|
# */
|
||||||
|
# let client = Client::debug(rocket()).expect("valid rocket instance");
|
||||||
let mut response = client.get("/").dispatch();
|
let mut response = client.get("/").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.into_string(), Some("Hello, world!".into()));
|
assert_eq!(response.into_string(), Some("Hello, world!".into()));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rocket_guide_tests"
|
name = "rocket_guide_tests"
|
||||||
version = "0.0.0"
|
version = "0.5.0-dev"
|
||||||
workspace = "../../"
|
workspace = "../../"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
|
@ -50,5 +50,5 @@ macro_rules! assert_form_parses_ok {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client(routes: Vec<rocket::Route>) -> rocket::local::blocking::Client {
|
pub fn client(routes: Vec<rocket::Route>) -> rocket::local::blocking::Client {
|
||||||
rocket::local::blocking::Client::debug("/", routes).unwrap()
|
rocket::local::blocking::Client::debug_with(routes).unwrap()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue