From dea940c7a85386a0ce103ef9c52060ada12daa05 Mon Sep 17 00:00:00 2001 From: Jeb Rosen Date: Sun, 14 Jun 2020 08:57:51 -0700 Subject: [PATCH] Defer execution of operations on 'Rocket' until their effects will be observed. This is a prerequisite for async on_attach fairings. 'Rocket' is now a builder wrapper around the 'Manifest' type, with operations being applied when needed by 'launch()', 'Client::new()', or 'inspect()'. 'inspect()' returns an '&Manifest', which now provides the methods that could be called on an '&Rocket'. --- contrib/codegen/src/database.rs | 8 +- contrib/lib/src/databases.rs | 11 +- contrib/lib/src/helmet/helmet.rs | 8 +- contrib/lib/src/templates/fairing.rs | 10 +- contrib/lib/src/templates/mod.rs | 8 +- contrib/lib/tests/databases.rs | 8 +- contrib/lib/tests/templates.rs | 16 +- core/lib/benches/simple-routing.rs | 2 +- core/lib/src/config/mod.rs | 4 +- core/lib/src/fairing/ad_hoc.rs | 10 +- core/lib/src/fairing/fairings.rs | 6 +- core/lib/src/fairing/mod.rs | 14 +- core/lib/src/lib.rs | 2 +- core/lib/src/local/client.rs | 20 +- core/lib/src/local/request.rs | 6 +- core/lib/src/request/request.rs | 14 +- core/lib/src/request/state.rs | 17 +- core/lib/src/request/tests.rs | 2 +- core/lib/src/rocket.rs | 398 +++++++++++++-------- core/lib/src/router/collider.rs | 4 +- core/lib/src/router/mod.rs | 8 +- examples/config/tests/common/mod.rs | 4 +- examples/cookies/src/tests.rs | 4 +- examples/fairings/src/main.rs | 4 +- examples/handlebars_templates/src/tests.rs | 6 +- examples/request_local_state/src/tests.rs | 4 +- examples/state/src/tests.rs | 9 +- examples/tera_templates/src/tests.rs | 6 +- examples/todo/src/main.rs | 4 +- examples/todo/src/tests.rs | 4 +- site/guide/9-configuration.md | 4 +- 31 files changed, 368 insertions(+), 257 deletions(-) diff --git a/contrib/codegen/src/database.rs b/contrib/codegen/src/database.rs index 8261721e..aa011e2e 100644 --- a/contrib/codegen/src/database.rs +++ b/contrib/codegen/src/database.rs @@ -93,8 +93,8 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result impl ::rocket::fairing::Fairing { use #databases::Poolable; - ::rocket::fairing::AdHoc::on_attach(#fairing_name, |rocket| { - let pool = #databases::database_config(#name, rocket.config()) + ::rocket::fairing::AdHoc::on_attach(#fairing_name, |mut rocket| { + let pool = #databases::database_config(#name, rocket.inspect().config()) .map(<#conn_type>::pool); match pool { @@ -118,8 +118,8 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result Option { - rocket.state::<#pool_type>() + pub fn get_one(manifest: &::rocket::Manifest) -> Option { + manifest.state::<#pool_type>() .and_then(|pool| pool.0.get().ok()) .map(#guard_type) } diff --git a/contrib/lib/src/databases.rs b/contrib/lib/src/databases.rs index 9aa27e22..b4ba4260 100644 --- a/contrib/lib/src/databases.rs +++ b/contrib/lib/src/databases.rs @@ -239,7 +239,7 @@ //! Returns a fairing that initializes the associated database connection //! pool. //! -//! * `fn get_one(&Rocket) -> Option` +//! * `fn get_one(&Manifest) -> Option` //! //! Retrieves a connection from the configured pool. Returns `Some` as long //! as `Self::fairing()` has been attached and there is at least one @@ -548,16 +548,17 @@ pub enum ConfigError { /// # .extra("databases", databases) /// # .expect("custom config okay"); /// # -/// # rocket::custom(config).attach(AdHoc::on_attach("Testing", |rocket| { +/// # rocket::custom(config).attach(AdHoc::on_attach("Testing", |mut rocket| { /// # { -/// let config = database_config("my_db", rocket.config()).unwrap(); +/// let manifest = rocket.inspect(); +/// let config = database_config("my_db", manifest.config()).unwrap(); /// assert_eq!(config.url, "db/db.sqlite"); /// assert_eq!(config.pool_size, 25); /// -/// let other_config = database_config("my_other_db", rocket.config()).unwrap(); +/// let other_config = database_config("my_other_db", manifest.config()).unwrap(); /// assert_eq!(other_config.url, "mysql://root:root@localhost/database"); /// -/// let error = database_config("invalid_db", rocket.config()).unwrap_err(); +/// let error = database_config("invalid_db", manifest.config()).unwrap_err(); /// assert_eq!(error, ConfigError::MissingKey); /// # } /// # diff --git a/contrib/lib/src/helmet/helmet.rs b/contrib/lib/src/helmet/helmet.rs index 8c5da983..e6a863eb 100644 --- a/contrib/lib/src/helmet/helmet.rs +++ b/contrib/lib/src/helmet/helmet.rs @@ -3,7 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rocket::http::uncased::UncasedStr; use rocket::fairing::{Fairing, Info, Kind}; -use rocket::{Request, Response, Rocket}; +use rocket::{Manifest, Request, Response}; use crate::helmet::*; @@ -201,9 +201,9 @@ impl Fairing for SpaceHelmet { self.apply(res); } - fn on_launch(&self, rocket: &Rocket) { - if rocket.config().tls_enabled() - && !rocket.config().environment.is_dev() + fn on_launch(&self, manifest: &Manifest) { + if manifest.config().tls_enabled() + && !manifest.config().environment.is_dev() && !self.is_enabled::() { warn_!("Space Helmet: deploying with TLS without enabling HSTS."); diff --git a/contrib/lib/src/templates/fairing.rs b/contrib/lib/src/templates/fairing.rs index 8e209b7b..e2a517a9 100644 --- a/contrib/lib/src/templates/fairing.rs +++ b/contrib/lib/src/templates/fairing.rs @@ -151,10 +151,12 @@ impl Fairing for TemplateFairing { /// The user's callback, if any was supplied, is called to customize the /// template engines. In debug mode, the `ContextManager::new` method /// initializes a directory watcher for auto-reloading of templates. - fn on_attach(&self, rocket: Rocket) -> Result { - let mut template_root = rocket.config().root_relative(DEFAULT_TEMPLATE_DIR); - match rocket.config().get_str("template_dir") { - Ok(dir) => template_root = rocket.config().root_relative(dir), + fn on_attach(&self, mut rocket: Rocket) -> Result { + let manifest = rocket.inspect(); + let config = manifest.config(); + let mut template_root = config.root_relative(DEFAULT_TEMPLATE_DIR); + match config.get_str("template_dir") { + Ok(dir) => template_root = config.root_relative(dir), Err(ConfigError::Missing(_)) => { /* ignore missing */ } Err(e) => { e.pretty_print(); diff --git a/contrib/lib/src/templates/mod.rs b/contrib/lib/src/templates/mod.rs index 0ba5e51d..b5ca1a2d 100644 --- a/contrib/lib/src/templates/mod.rs +++ b/contrib/lib/src/templates/mod.rs @@ -141,7 +141,7 @@ use serde_json::{Value, to_value}; use std::borrow::Cow; use std::path::PathBuf; -use rocket::{Rocket, State}; +use rocket::{Manifest, State}; use rocket::request::Request; use rocket::fairing::Fairing; use rocket::response::{self, Content, Responder}; @@ -339,14 +339,14 @@ impl Template { /// /// # context.insert("test", "test"); /// # #[allow(unused_variables)] - /// let template = Template::show(client.rocket(), "index", context); + /// let template = Template::show(client.manifest(), "index", context); /// } /// ``` #[inline] - pub fn show(rocket: &Rocket, name: S, context: C) -> Option + pub fn show(manifest: &Manifest, name: S, context: C) -> Option where S: Into>, C: Serialize { - let ctxt = rocket.state::().map(ContextManager::context).or_else(|| { + let ctxt = manifest.state::().map(ContextManager::context).or_else(|| { warn!("Uninitialized template context: missing fairing."); info!("To use templates, you must attach `Template::fairing()`."); info!("See the `Template` documentation for more information."); diff --git a/contrib/lib/tests/databases.rs b/contrib/lib/tests/databases.rs index ca51b8d6..60cc16c3 100644 --- a/contrib/lib/tests/databases.rs +++ b/contrib/lib/tests/databases.rs @@ -33,8 +33,8 @@ mod rusqlite_integration_test { .finalize() .unwrap(); - let rocket = rocket::custom(config).attach(SqliteDb::fairing()); - let mut conn = SqliteDb::get_one(&rocket).expect("unable to get connection"); + let mut rocket = rocket::custom(config).attach(SqliteDb::fairing()); + let mut conn = SqliteDb::get_one(rocket.inspect()).expect("unable to get connection"); // Rusqlite's `transaction()` method takes `&mut self`; this tests the // presence of a `DerefMut` trait on the generated connection type. @@ -54,8 +54,8 @@ mod rusqlite_integration_test { .finalize() .unwrap(); - let rocket = rocket::custom(config).attach(SqliteDb::fairing()); - let conn = SqliteDb::get_one(&rocket).expect("unable to get connection"); + let mut rocket = rocket::custom(config).attach(SqliteDb::fairing()); + let conn = SqliteDb::get_one(rocket.inspect()).expect("unable to get connection"); let _: i32 = conn.query_row("SELECT 1", &[] as &[&dyn ToSql], |row| row.get(0)).expect("get row"); } } diff --git a/contrib/lib/tests/templates.rs b/contrib/lib/tests/templates.rs index 2f9b029e..680db191 100644 --- a/contrib/lib/tests/templates.rs +++ b/contrib/lib/tests/templates.rs @@ -51,17 +51,18 @@ mod templates_tests { #[test] fn test_tera_templates() { - let rocket = rocket(); + let mut rocket = rocket(); + let manifest = rocket.inspect(); let mut map = HashMap::new(); map.insert("title", "_test_"); map.insert("content", "