From ec9b5816a8bb17c85037e5319c1f7d5f2c5e0385 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Thu, 22 Oct 2020 03:27:04 -0700 Subject: [PATCH] Remove 'rocket::inspect()', 'Cargo'. This commit reverts most of dea940c7 and d89c7024. The "fix" is to run attach fairings on a new thread. If a runtime is already running, it is used. Otherwise, the future is executed in a single-threaded executor. --- contrib/codegen/src/database.rs | 18 +- contrib/lib/src/databases.rs | 78 ++-- contrib/lib/src/helmet/helmet.rs | 8 +- contrib/lib/src/lib.rs | 2 +- contrib/lib/src/serve.rs | 2 +- contrib/lib/src/templates/fairing.rs | 6 +- contrib/lib/src/templates/mod.rs | 10 +- contrib/lib/tests/databases.rs | 9 +- contrib/lib/tests/templates.rs | 24 +- core/lib/benches/simple-routing.rs | 2 +- core/lib/src/config/mod.rs | 4 +- core/lib/src/data/data.rs | 2 +- core/lib/src/fairing/ad_hoc.rs | 13 +- core/lib/src/fairing/fairings.rs | 6 +- core/lib/src/fairing/mod.rs | 14 +- core/lib/src/lib.rs | 6 +- core/lib/src/local/asynchronous/client.rs | 11 +- core/lib/src/local/blocking/client.rs | 6 +- core/lib/src/local/client.rs | 20 +- core/lib/src/request/state.rs | 17 +- core/lib/src/rocket.rs | 447 ++++++--------------- core/lib/tests/attach-inspect.rs | 29 +- core/lib/tests/twice_managed_state.rs | 6 +- examples/config/src/tests.rs | 18 +- 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 | 14 +- examples/tera_templates/src/tests.rs | 6 +- examples/todo/src/main.rs | 6 +- examples/todo/src/tests.rs | 2 +- site/guide/9-configuration.md | 10 +- 33 files changed, 293 insertions(+), 521 deletions(-) diff --git a/contrib/codegen/src/database.rs b/contrib/codegen/src/database.rs index 4c4a6725..6d844267 100644 --- a/contrib/codegen/src/database.rs +++ b/contrib/codegen/src/database.rs @@ -72,10 +72,12 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result - /// The request guard type. #vis struct #guard_type(#databases::Connection); }; + let pool = quote_spanned!(span => #databases::ConnectionPool); + let conn = quote_spanned!(span => #databases::Connection); + Ok(quote! { #request_guard_type @@ -83,26 +85,26 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result impl ::rocket::fairing::Fairing { - <#databases::ConnectionPool>::fairing(#fairing_name, #name) + <#pool>::fairing(#fairing_name, #name) } /// Retrieves a connection of type `Self` from the `rocket` /// instance. Returns `Some` as long as `Self::fairing()` has been /// attached. - pub async fn get_one(cargo: &::rocket::Cargo) -> Option { - <#databases::ConnectionPool>::get_one(cargo).await.map(Self) + pub async fn get_one(__rocket: &::rocket::Rocket) -> Option { + <#pool>::get_one(&__rocket).await.map(Self) } /// Runs the provided closure on a thread from a threadpool. The /// closure will be passed an `&mut r2d2::PooledConnection`. /// `.await`ing the return value of this function yields the value /// returned by the closure. - pub async fn run(&self, f: F) -> R + pub async fn run(&self, __f: F) -> R where F: FnOnce(&mut #conn_type) -> R + Send + 'static, R: Send + 'static, { - self.0.run(f).await + self.0.run(__f).await } } @@ -110,8 +112,8 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result #request::FromRequest<'a, 'r> for #guard_type { type Error = (); - async fn from_request(req: &'a #request::Request<'r>) -> #request::Outcome { - <#databases::Connection>::from_request(req).await.map(Self) + async fn from_request(__r: &'a #request::Request<'r>) -> #request::Outcome { + <#conn>::from_request(__r).await.map(Self) } } }.into()) diff --git a/contrib/lib/src/databases.rs b/contrib/lib/src/databases.rs index de4f9aec..8dbf0997 100644 --- a/contrib/lib/src/databases.rs +++ b/contrib/lib/src/databases.rs @@ -198,7 +198,7 @@ //! Returns a fairing that initializes the associated database connection //! pool. //! -//! * `async fn get_one(&Cargo) -> Option` +//! * `async fn get_one(&Rocket) -> Option` //! //! Retrieves a connection wrapper from the configured pool. Returns `Some` //! as long as `Self::fairing()` has been attached. @@ -405,7 +405,7 @@ use self::r2d2::ManageConnection; /// timeout = 5 /// ``` /// -/// ...`Config::from("my_database", cargo)` would return the following struct: +/// ...`Config::from("my_database", rocket)` would return the following struct: /// /// ```rust /// # use rocket_contrib::databases::Config; @@ -455,32 +455,29 @@ impl Config { /// /// use rocket_contrib::databases::Config; /// - /// fn pool(cargo: &rocket::Cargo) { - /// let config = Config::from("my_db", cargo).unwrap(); + /// fn pool(rocket: &rocket::Rocket) { + /// let config = Config::from("my_db", rocket).unwrap(); /// assert_eq!(config.url, "db/db.sqlite"); /// assert_eq!(config.pool_size, 25); /// - /// let config = Config::from("my_other_db", cargo).unwrap(); + /// let config = Config::from("my_other_db", rocket).unwrap(); /// assert_eq!(config.url, "mysql://root:root@localhost/database"); - /// assert_eq!(config.pool_size, cargo.config().workers as u32); + /// assert_eq!(config.pool_size, rocket.config().workers as u32); /// - /// let config = Config::from("unknown_db", cargo); + /// let config = Config::from("unknown_db", rocket); /// assert!(config.is_err()) /// } /// # - /// # rocket::async_test(async { - /// # let config = Figment::from(rocket::Config::default()).merge(toml); - /// # let mut rocket = rocket::custom(config); - /// # let cargo = rocket.inspect().await; - /// # pool(cargo); - /// # }); + /// # let config = Figment::from(rocket::Config::default()).merge(toml); + /// # let rocket = rocket::custom(config); + /// # pool(&rocket); /// # } /// ``` - pub fn from(db_name: &str, cargo: &rocket::Cargo) -> Result { + pub fn from(db_name: &str, rocket: &rocket::Rocket) -> Result { let db_key = format!("databases.{}", db_name); let key = |name: &str| format!("{}.{}", db_key, name); - Figment::from(cargo.figment()) - .merge(Serialized::default(&key("pool_size"), cargo.config().workers)) + Figment::from(rocket.figment()) + .merge(Serialized::default(&key("pool_size"), rocket.config().workers)) .merge(Serialized::default(&key("timeout"), 5)) .extract_inner::(&db_key) } @@ -578,8 +575,8 @@ impl From for Error { /// type Manager = foo::ConnectionManager; /// type Error = foo::Error; /// -/// fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { -/// let config = Config::from(db_name, cargo)?; +/// fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { +/// let config = Config::from(db_name, rocket)?; /// let manager = foo::ConnectionManager::new(&config.url).map_err(Error::Custom)?; /// Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) /// } @@ -607,7 +604,7 @@ pub trait Poolable: Send + Sized + 'static { /// Creates an `r2d2` connection pool for `Manager::Connection`, returning /// the pool on success. - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult; } /// A type alias for the return type of [`Poolable::pool()`]. @@ -619,8 +616,8 @@ impl Poolable for diesel::SqliteConnection { type Manager = diesel::r2d2::ConnectionManager; type Error = std::convert::Infallible; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let manager = diesel::r2d2::ConnectionManager::new(&config.url); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) } @@ -631,8 +628,8 @@ impl Poolable for diesel::PgConnection { type Manager = diesel::r2d2::ConnectionManager; type Error = std::convert::Infallible; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let manager = diesel::r2d2::ConnectionManager::new(&config.url); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) } @@ -643,8 +640,8 @@ impl Poolable for diesel::MysqlConnection { type Manager = diesel::r2d2::ConnectionManager; type Error = std::convert::Infallible; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let manager = diesel::r2d2::ConnectionManager::new(&config.url); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) } @@ -656,8 +653,8 @@ impl Poolable for postgres::Client { type Manager = r2d2_postgres::PostgresConnectionManager; type Error = postgres::Error; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let url = config.url.parse().map_err(Error::Custom)?; let manager = r2d2_postgres::PostgresConnectionManager::new(url, postgres::tls::NoTls); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) @@ -669,8 +666,8 @@ impl Poolable for mysql::Conn { type Manager = r2d2_mysql::MysqlConnectionManager; type Error = std::convert::Infallible; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let opts = mysql::OptsBuilder::from_opts(&config.url); let manager = r2d2_mysql::MysqlConnectionManager::new(opts); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) @@ -682,8 +679,8 @@ impl Poolable for rusqlite::Connection { type Manager = r2d2_sqlite::SqliteConnectionManager; type Error = std::convert::Infallible; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let manager = r2d2_sqlite::SqliteConnectionManager::file(&*config.url); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) } @@ -695,8 +692,8 @@ impl Poolable for memcache::Client { // Unused, but we might want it in the future without a breaking change. type Error = memcache::MemcacheError; - fn pool(db_name: &str, cargo: &rocket::Cargo) -> PoolResult { - let config = Config::from(db_name, cargo)?; + fn pool(db_name: &str, rocket: &rocket::Rocket) -> PoolResult { + let config = Config::from(db_name, rocket)?; let manager = r2d2_memcache::MemcacheConnectionManager::new(&*config.url); Ok(r2d2::Pool::builder().max_size(config.pool_size).build(manager)?) } @@ -759,15 +756,14 @@ macro_rules! dberr { impl ConnectionPool { pub fn fairing(fairing_name: &'static str, db: &'static str) -> impl Fairing { - AdHoc::on_attach(fairing_name, move |mut rocket| async move { - let cargo = rocket.inspect().await; - let config = match Config::from(db, cargo) { + AdHoc::on_attach(fairing_name, move |rocket| async move { + let config = match Config::from(db, &rocket) { Ok(config) => config, Err(e) => dberr!("config", db, "{}", e, rocket), }; let pool_size = config.pool_size; - match C::pool(db, cargo) { + match C::pool(db, &rocket) { Ok(pool) => Ok(rocket.manage(ConnectionPool:: { pool, config, semaphore: Arc::new(Semaphore::new(pool_size as usize)), @@ -805,16 +801,16 @@ impl ConnectionPool { } #[inline] - pub async fn get_one(cargo: &rocket::Cargo) -> Option> { - match cargo.state::() { + pub async fn get_one(rocket: &rocket::Rocket) -> Option> { + match rocket.state::() { Some(pool) => pool.get().await.ok(), None => None } } #[inline] - pub async fn get_pool(cargo: &rocket::Cargo) -> Option { - cargo.state::().map(|pool| pool.clone()) + pub async fn get_pool(rocket: &rocket::Rocket) -> Option { + rocket.state::().map(|pool| pool.clone()) } } diff --git a/contrib/lib/src/helmet/helmet.rs b/contrib/lib/src/helmet/helmet.rs index 71783521..91d036ae 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::{Cargo, Request, Response}; +use rocket::{Rocket, Request, Response}; use crate::helmet::*; @@ -201,9 +201,9 @@ impl Fairing for SpaceHelmet { self.apply(res); } - fn on_launch(&self, cargo: &Cargo) { - if cargo.config().tls_enabled() - && cargo.figment().profile() != rocket::Config::DEBUG_PROFILE + fn on_launch(&self, rocket: &Rocket) { + if rocket.config().tls_enabled() + && rocket.figment().profile() != rocket::Config::DEBUG_PROFILE && !self.is_enabled::() { warn_!("Space Helmet: deploying with TLS without enabling HSTS."); diff --git a/contrib/lib/src/lib.rs b/contrib/lib/src/lib.rs index bc722956..8c157418 100644 --- a/contrib/lib/src/lib.rs +++ b/contrib/lib/src/lib.rs @@ -25,7 +25,7 @@ //! * [${database}_pool](databases) - Database Configuration and Pooling //! * [helmet](helmet) - Fairing for Security and Privacy Headers //! -//! The recommend way to include features from this crate via Cargo in your +//! The recommend way to include features from this crate via Rocket in your //! project is by adding a `[dependencies.rocket_contrib]` section to your //! `Cargo.toml` file, setting `default-features` to false, and specifying //! features manually. For example, to use the JSON module, you would add: diff --git a/contrib/lib/src/serve.rs b/contrib/lib/src/serve.rs index 84660f54..d6f288b1 100644 --- a/contrib/lib/src/serve.rs +++ b/contrib/lib/src/serve.rs @@ -187,7 +187,7 @@ impl std::ops::BitOr for Options { /// ## Relative Paths /// /// In the example above, `/static` is an absolute path. If your static files -/// are stored relative to your crate and your project is managed by Cargo, use +/// are stored relative to your crate and your project is managed by Rocket, use /// the [`crate_relative!`] macro to obtain a path that is relative to your /// crate's root. For example, to serve files in the `static` subdirectory of /// your crate at `/`, you might write: diff --git a/contrib/lib/src/templates/fairing.rs b/contrib/lib/src/templates/fairing.rs index 6f818c6b..6d5bbaac 100644 --- a/contrib/lib/src/templates/fairing.rs +++ b/contrib/lib/src/templates/fairing.rs @@ -138,10 +138,10 @@ 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. - async fn on_attach(&self, mut rocket: Rocket) -> Result { + async fn on_attach(&self, rocket: Rocket) -> Result { use rocket::figment::{Source, value::magic::RelativePathBuf}; - let configured_dir = rocket.figment().await + let configured_dir = rocket.figment() .extract_inner::("template_dir") .map(|path| path.relative()); @@ -173,7 +173,7 @@ impl Fairing for TemplateFairing { #[cfg(debug_assertions)] async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &mut rocket::Data) { - let cm = req.guard::>().await + let cm = req.managed_state::() .expect("Template ContextManager registered in on_attach"); cm.reload_if_needed(&*self.custom_callback); diff --git a/contrib/lib/src/templates/mod.rs b/contrib/lib/src/templates/mod.rs index 10f8cd8a..5459644d 100644 --- a/contrib/lib/src/templates/mod.rs +++ b/contrib/lib/src/templates/mod.rs @@ -104,7 +104,7 @@ //! can be any type that implements [`Serialize`] from [`serde`] and would //! serialize to an `Object` value. //! -//! In debug mode (without the `--release` flag passed to `cargo`), templates +//! In debug mode (without the `--release` flag passed to `rocket`), templates //! will be automatically reloaded from disk if any changes have been made to //! the templates directory since the previous request. In release builds, //! template reloading is disabled to improve performance and cannot be enabled. @@ -140,7 +140,7 @@ use serde_json::{Value, to_value}; use std::borrow::Cow; use std::path::PathBuf; -use rocket::Cargo; +use rocket::Rocket; use rocket::request::Request; use rocket::fairing::Fairing; use rocket::response::{self, Content, Responder}; @@ -337,14 +337,14 @@ impl Template { /// /// # context.insert("test", "test"); /// # #[allow(unused_variables)] - /// let template = Template::show(client.cargo(), "index", context); + /// let template = Template::show(client.rocket(), "index", context); /// } /// ``` #[inline] - pub fn show(cargo: &Cargo, name: S, context: C) -> Option + pub fn show(rocket: &Rocket, name: S, context: C) -> Option where S: Into>, C: Serialize { - let ctxt = cargo.state::().map(ContextManager::context).or_else(|| { + let ctxt = rocket.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 69b4a2c7..98549c9a 100644 --- a/contrib/lib/tests/databases.rs +++ b/contrib/lib/tests/databases.rs @@ -33,18 +33,21 @@ mod rusqlite_integration_test { .merge(("databases", map!["test_db" => &options])) .merge(("databases", map!["test_db_2" => &options])); - let mut rocket = rocket::custom(config) + let rocket = rocket::custom(config) .attach(SqliteDb::fairing()) .attach(SqliteDb2::fairing()); - let conn = SqliteDb::get_one(rocket.inspect().await).await + let conn = SqliteDb::get_one(&rocket).await .expect("unable to get connection"); // Rusqlite's `transaction()` method takes `&mut self`; this tests that // the &mut method can be called inside the closure passed to `run()`. conn.run(|conn| { let tx = conn.transaction().unwrap(); - let _: i32 = tx.query_row("SELECT 1", &[] as &[&dyn ToSql], |row| row.get(0)).expect("get row"); + let _: i32 = tx.query_row( + "SELECT 1", &[] as &[&dyn ToSql], |row| row.get(0) + ).expect("get row"); + tx.commit().expect("committed transaction"); }).await; } diff --git a/contrib/lib/tests/templates.rs b/contrib/lib/tests/templates.rs index 772c3491..a584de39 100644 --- a/contrib/lib/tests/templates.rs +++ b/contrib/lib/tests/templates.rs @@ -44,20 +44,19 @@ mod templates_tests { const ESCAPED_EXPECTED: &'static str = "\nh_start\ntitle: _test_\nh_end\n\n\n<script />\n\nfoot\n"; - #[rocket::async_test] - async fn test_tera_templates() { - let mut rocket = rocket(); - let cargo = rocket.inspect().await; + #[test] + fn test_tera_templates() { + let rocket = rocket(); let mut map = HashMap::new(); map.insert("title", "_test_"); map.insert("content", "