From bc1b90cbdbf2b57a8ef680ed320458986c12e357 Mon Sep 17 00:00:00 2001 From: Jeb Rosen Date: Sun, 14 Jun 2020 08:57:55 -0700 Subject: [PATCH] Add '#[rocket::main]' attribute and make 'launch()' an 'async fn'. '#[rocket::main]' works like '#[rocket::async_test]', but it uses tokio's multithreaded scheduler. --- contrib/lib/src/databases.rs | 17 +++-- contrib/lib/src/serve.rs | 30 +++++--- core/codegen/src/attribute/async_entry.rs | 83 +++++++++++++++++++++++ core/codegen/src/attribute/async_test.rs | 43 ------------ core/codegen/src/attribute/mod.rs | 2 +- core/codegen/src/lib.rs | 7 +- core/lib/src/catcher.rs | 5 +- core/lib/src/error.rs | 18 ++--- core/lib/src/handler.rs | 12 ++-- core/lib/src/lib.rs | 16 ++++- core/lib/src/request/state.rs | 6 +- core/lib/src/response/flash.rs | 5 +- core/lib/src/rocket.rs | 76 +++++++-------------- core/lib/src/shutdown.rs | 4 +- examples/config/src/main.rs | 5 +- examples/content_types/src/main.rs | 5 +- examples/cookies/src/main.rs | 5 +- examples/errors/src/main.rs | 5 +- examples/fairings/src/main.rs | 5 +- examples/form_kitchen_sink/src/main.rs | 5 +- examples/form_validation/src/main.rs | 5 +- examples/handlebars_templates/src/main.rs | 5 +- examples/hello_2018/src/main.rs | 5 +- examples/hello_person/src/main.rs | 5 +- examples/hello_world/src/main.rs | 5 +- examples/json/src/main.rs | 5 +- examples/managed_queue/src/main.rs | 5 +- examples/manual_routes/src/main.rs | 5 +- examples/msgpack/src/main.rs | 5 +- examples/optional_redirect/src/main.rs | 5 +- examples/pastebin/src/main.rs | 5 +- examples/query_params/src/main.rs | 5 +- examples/ranking/src/main.rs | 5 +- examples/raw_sqlite/src/main.rs | 5 +- examples/raw_upload/src/main.rs | 5 +- examples/redirect/src/main.rs | 5 +- examples/request_guard/src/main.rs | 5 +- examples/request_local_state/src/main.rs | 5 +- examples/session/src/main.rs | 5 +- examples/state/src/main.rs | 5 +- examples/static_files/src/main.rs | 5 +- examples/stream/src/main.rs | 5 +- examples/tera_templates/src/main.rs | 5 +- examples/testing/src/main.rs | 5 +- examples/tls/src/main.rs | 5 +- examples/todo/src/main.rs | 5 +- examples/uuid/src/main.rs | 5 +- site/guide/3-overview.md | 6 +- 48 files changed, 292 insertions(+), 203 deletions(-) create mode 100644 core/codegen/src/attribute/async_entry.rs delete mode 100644 core/codegen/src/attribute/async_test.rs diff --git a/contrib/lib/src/databases.rs b/contrib/lib/src/databases.rs index f9f04ede..79067550 100644 --- a/contrib/lib/src/databases.rs +++ b/contrib/lib/src/databases.rs @@ -62,10 +62,12 @@ //! #[database("sqlite_logs")] //! struct LogsDbConn(diesel::SqliteConnection); //! -//! fn main() { +//! #[rocket::main] +//! async fn main() { //! rocket::ignite() //! .attach(LogsDbConn::fairing()) -//! .launch(); +//! .launch() +//! .await; //! } //! # } fn main() {} //! ``` @@ -150,7 +152,8 @@ //! use std::collections::HashMap; //! use rocket::config::{Config, Environment, Value}; //! -//! fn main() { +//! #[rocket::main] +//! async fn main() { //! let mut database_config = HashMap::new(); //! let mut databases = HashMap::new(); //! @@ -164,7 +167,7 @@ //! .finalize() //! .unwrap(); //! -//! rocket::custom(config).launch(); +//! rocket::custom(config).launch().await; //! } //! # } fn main() {} //! ``` @@ -263,7 +266,8 @@ //! #[database("my_db")] //! struct MyDatabase(diesel::SqliteConnection); //! -//! fn main() { +//! #[rocket::main] +//! async fn main() { //! # let mut db_config = HashMap::new(); //! # let mut databases = HashMap::new(); //! # @@ -278,7 +282,8 @@ //! # //! rocket::custom(config) //! .attach(MyDatabase::fairing()) -//! .launch(); +//! .launch() +//! .await; //! } //! # } fn main() {} //! ``` diff --git a/contrib/lib/src/serve.rs b/contrib/lib/src/serve.rs index 5a41e2f9..9217410f 100644 --- a/contrib/lib/src/serve.rs +++ b/contrib/lib/src/serve.rs @@ -135,11 +135,13 @@ impl std::ops::BitOr for Options { /// # extern crate rocket_contrib; /// use rocket_contrib::serve::StaticFiles; /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/public", StaticFiles::from("/static")) -/// .launch(); +/// .launch() +/// .await; /// # } /// } /// ``` @@ -161,11 +163,13 @@ impl std::ops::BitOr for Options { /// # extern crate rocket_contrib; /// use rocket_contrib::serve::StaticFiles; /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/", StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static"))) -/// .launch(); +/// .launch() +/// .await; /// # } /// } /// ``` @@ -196,11 +200,13 @@ impl StaticFiles { /// # extern crate rocket_contrib; /// use rocket_contrib::serve::StaticFiles; /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/static", StaticFiles::from("/www/public")) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` @@ -212,11 +218,13 @@ impl StaticFiles { /// # extern crate rocket_contrib; /// use rocket_contrib::serve::StaticFiles; /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/static", StaticFiles::from("/www/public").rank(30)) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` @@ -240,13 +248,15 @@ impl StaticFiles { /// # extern crate rocket_contrib; /// use rocket_contrib::serve::{StaticFiles, Options}; /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { /// let options = Options::Index | Options::DotFiles; /// rocket::ignite() /// .mount("/static", StaticFiles::from("/www/public")) /// .mount("/pub", StaticFiles::new("/www/public", options).rank(-1)) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` diff --git a/core/codegen/src/attribute/async_entry.rs b/core/codegen/src/attribute/async_entry.rs new file mode 100644 index 00000000..c6ef4eb8 --- /dev/null +++ b/core/codegen/src/attribute/async_entry.rs @@ -0,0 +1,83 @@ +use proc_macro::{TokenStream, Span}; +use devise::{syn, Result}; + +use crate::proc_macro2::TokenStream as TokenStream2; +use crate::syn_ext::syn_to_diag; + +#[derive(Copy, Clone)] +enum Kind { + Main, + Test, +} + +impl Kind { + // The name of the attribute, used for error messages + fn attr_name(&self) -> &'static str { + match self { + Kind::Main => "main", + Kind::Test => "async_test", + } + } + + // Attributes to decorate the generated function with + fn attrs(&self) -> Option { + match self { + Kind::Main => None, + Kind::Test => Some(quote!{ #[test] }), + } + } + + // The path to the function to call + fn fn_path(&self) -> TokenStream2 { + match self { + Kind::Main => quote! { rocket :: async_main }, + Kind::Test => quote! { rocket :: async_test }, + } + } +} + +fn parse_input(input: TokenStream, attr_name: &str) -> Result { + let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag) + .map_err(|diag| diag.help(format!("`#[{}]` can only be applied to async functions", attr_name)))?; + + if function.sig.asyncness.is_none() { + return Err(Span::call_site().error(format!("`#[{}]` can only be applied to async functions", attr_name))) + } + + if !function.sig.inputs.is_empty() { + return Err(Span::call_site().error(format!("`#[{}]` can only be applied to functions with no parameters", attr_name))); + } + + Ok(function) +} + +fn _async_entry(_args: TokenStream, input: TokenStream, kind: Kind) -> Result { + let function = parse_input(input, kind.attr_name())?; + + let attrs = &function.attrs; + let vis = &function.vis; + let name = &function.sig.ident; + let output = &function.sig.output; + let body = &function.block; + + let test_attr = kind.attrs(); + let fn_path = kind.fn_path(); + + Ok(quote! { + #test_attr + #(#attrs)* + #vis fn #name() #output { + #fn_path (async move { + #body + }) + } + }.into()) +} + +pub fn async_test_attribute(args: TokenStream, input: TokenStream) -> TokenStream { + _async_entry(args, input, Kind::Test).unwrap_or_else(|d| { d.emit(); TokenStream::new() }) +} + +pub fn main_attribute(args: TokenStream, input: TokenStream) -> TokenStream { + _async_entry(args, input, Kind::Main).unwrap_or_else(|d| { d.emit(); TokenStream::new() }) +} diff --git a/core/codegen/src/attribute/async_test.rs b/core/codegen/src/attribute/async_test.rs deleted file mode 100644 index 2a8caa1c..00000000 --- a/core/codegen/src/attribute/async_test.rs +++ /dev/null @@ -1,43 +0,0 @@ -use proc_macro::{TokenStream, Span}; -use devise::{syn, Result}; - -use crate::syn_ext::syn_to_diag; - -fn parse_input(input: TokenStream) -> Result { - let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag) - .map_err(|diag| diag.help("`#[async_test]` can only be applied to async functions"))?; - - if function.sig.asyncness.is_none() { - return Err(Span::call_site().error("`#[async_test]` can only be applied to async functions")) - } - - if !function.sig.inputs.is_empty() { - return Err(Span::call_site().error("`#[async_test]` can only be applied to functions with no parameters")); - } - - Ok(function) -} - -pub fn _async_test(_args: TokenStream, input: TokenStream) -> Result { - let function = parse_input(input)?; - - let attrs = &function.attrs; - let vis = &function.vis; - let name = &function.sig.ident; - let output = &function.sig.output; - let body = &function.block; - - Ok(quote! { - #[test] - #(#attrs)* - #vis fn #name() #output { - rocket::async_test(async move { - #body - }) - } - }.into()) -} - -pub fn async_test_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - _async_test(args, input).unwrap_or_else(|d| { d.emit(); TokenStream::new() }) -} diff --git a/core/codegen/src/attribute/mod.rs b/core/codegen/src/attribute/mod.rs index d1f41ad0..f3b72770 100644 --- a/core/codegen/src/attribute/mod.rs +++ b/core/codegen/src/attribute/mod.rs @@ -1,4 +1,4 @@ -pub mod async_test; +pub mod async_entry; pub mod catch; pub mod route; pub mod segments; diff --git a/core/codegen/src/lib.rs b/core/codegen/src/lib.rs index 29392020..9d4662b3 100644 --- a/core/codegen/src/lib.rs +++ b/core/codegen/src/lib.rs @@ -407,7 +407,12 @@ pub fn catch(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn async_test(args: TokenStream, input: TokenStream) -> TokenStream { - emit!(attribute::async_test::async_test_attribute(args, input)) + emit!(attribute::async_entry::async_test_attribute(args, input)) +} + +#[proc_macro_attribute] +pub fn main(args: TokenStream, input: TokenStream) -> TokenStream { + emit!(attribute::async_entry::main_attribute(args, input)) } /// Derive for the [`FromFormValue`] trait. diff --git a/core/lib/src/catcher.rs b/core/lib/src/catcher.rs index 5c011dbd..bd0bf557 100644 --- a/core/lib/src/catcher.rs +++ b/core/lib/src/catcher.rs @@ -52,9 +52,10 @@ use yansi::Color::*; /// format!("I couldn't find '{}'. Try something else?", req.uri()) /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { // We don't actually want to launch the server in an example. -/// rocket::ignite().register(catchers![internal_error, not_found]).launch(); +/// rocket::ignite().register(catchers![internal_error, not_found]).launch().await; /// # } /// } /// ``` diff --git a/core/lib/src/error.rs b/core/lib/src/error.rs index e8786121..7e1bb34e 100644 --- a/core/lib/src/error.rs +++ b/core/lib/src/error.rs @@ -65,8 +65,8 @@ pub enum LaunchErrorKind { /// ```rust /// use rocket::error::Error; /// -/// # if false { -/// if let Err(error) = rocket::ignite().launch() { +/// # let _ = async { +/// if let Err(error) = rocket::ignite().launch().await { /// match error { /// Error::Launch(error) => { /// // This case is only reached if launching failed. This println "inspects" the error. @@ -82,20 +82,20 @@ pub enum LaunchErrorKind { /// } /// } /// -/// # } +/// # }; /// ``` /// /// When a value of this type panics, the corresponding error message is pretty /// printed to the console. The following illustrates this: /// /// ```rust -/// # if false { -/// let error = rocket::ignite().launch(); +/// # let _ = async { +/// let error = rocket::ignite().launch().await; /// /// // This call to drop (explicit here for demonstration) will result in /// // `error` being pretty-printed to the console along with a `panic!`. /// drop(error); -/// # } +/// # }; /// ``` /// /// # Usage @@ -136,14 +136,14 @@ impl LaunchError { /// /// ```rust /// use rocket::error::Error; - /// # if false { - /// if let Err(error) = rocket::ignite().launch() { + /// # let _ = async { + /// if let Err(error) = rocket::ignite().launch().await { /// match error { /// Error::Launch(err) => println!("Found a launch error: {}", err.kind()), /// Error::Run(err) => println!("Error at runtime"), /// } /// } - /// # } + /// # }; /// ``` #[inline] pub fn kind(&self) -> &LaunchErrorKind { diff --git a/core/lib/src/handler.rs b/core/lib/src/handler.rs index 82693968..0ea0a5b8 100644 --- a/core/lib/src/handler.rs +++ b/core/lib/src/handler.rs @@ -65,11 +65,13 @@ pub type HandlerFuture<'r> = BoxFuture<'r, Outcome<'r>>; /// } /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/", CustomHandler(Kind::Simple)) -/// .launch(); +/// .launch() +/// .await; /// # } /// } /// ``` @@ -112,12 +114,14 @@ pub type HandlerFuture<'r> = BoxFuture<'r, Outcome<'r>>; /// } /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/", routes![custom_handler]) /// .manage(Kind::Simple) -/// .launch(); +/// .launch() +/// .await; /// # } /// } /// ``` diff --git a/core/lib/src/lib.rs b/core/lib/src/lib.rs index 1eba938f..e7a3fa16 100644 --- a/core/lib/src/lib.rs +++ b/core/lib/src/lib.rs @@ -67,9 +67,10 @@ //! "Hello, world!" //! } //! -//! fn main() { +//! #[rocket::main] +//! async fn main() { //! # if false { // We don't actually want to launch the server in an example. -//! rocket::ignite().mount("/", routes![hello]).launch(); +//! rocket::ignite().mount("/", routes![hello]).launch().await; //! # } //! } //! ``` @@ -164,3 +165,14 @@ pub fn async_test(fut: impl std::future::Future + Send) -> R { .expect("create tokio runtime") .block_on(fut) } + +/// WARNING: This is unstable! Do not use this method outside of Rocket! +#[doc(hidden)] +pub fn async_main(fut: impl std::future::Future + Send) -> R { + tokio::runtime::Builder::new() + .threaded_scheduler() + .enable_all() + .build() + .expect("create tokio runtime") + .block_on(fut) +} diff --git a/core/lib/src/request/state.rs b/core/lib/src/request/state.rs index 3c4b48bb..a40bd842 100644 --- a/core/lib/src/request/state.rs +++ b/core/lib/src/request/state.rs @@ -42,7 +42,8 @@ use crate::http::Status; /// state.inner().user_val.as_str() /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// let config = MyConfig { /// user_val: "user input".to_string() /// }; @@ -51,7 +52,8 @@ use crate::http::Status; /// rocket::ignite() /// .mount("/", routes![index, raw_config_value]) /// .manage(config) -/// .launch(); +/// .launch() +/// .await; /// # } /// } /// ``` diff --git a/core/lib/src/response/flash.rs b/core/lib/src/response/flash.rs index ba47233a..b96757e4 100644 --- a/core/lib/src/response/flash.rs +++ b/core/lib/src/response/flash.rs @@ -69,9 +69,10 @@ const FLASH_COOKIE_DELIM: char = ':'; /// .unwrap_or_else(|| "Welcome!".to_string()) /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { // We don't actually want to launch the server in an example. -/// rocket::ignite().mount("/", routes![login, index]).launch(); +/// rocket::ignite().mount("/", routes![login, index]).launch().await; /// # } /// } /// ``` diff --git a/core/lib/src/rocket.rs b/core/lib/src/rocket.rs index 4fe7ef8d..b4aa19eb 100644 --- a/core/lib/src/rocket.rs +++ b/core/lib/src/rocket.rs @@ -656,10 +656,11 @@ impl Rocket { /// "Hello!" /// } /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite().mount("/hello", routes![hi]) - /// # .launch(); + /// # .launch().await; /// # } /// } /// ``` @@ -677,10 +678,10 @@ impl Rocket { /// Outcome::from(req, "Hello!") /// } /// - /// # if false { // We don't actually want to launch the server in an example. + /// # let _ = async { // We don't actually want to launch the server in an example. /// rocket::ignite().mount("/hello", vec![Route::new(Get, "/world", hi)]) - /// # .launch(); - /// # } + /// # .launch().await; + /// # }; /// ``` #[inline] pub fn mount>>(mut self, base: &str, routes: R) -> Self { @@ -718,11 +719,12 @@ impl Rocket { /// format!("I couldn't find '{}'. Try something else?", req.uri()) /// } /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite() /// .register(catchers![internal_error, not_found]) - /// # .launch(); + /// # .launch().await; /// # } /// } /// ``` @@ -760,12 +762,14 @@ impl Rocket { /// format!("The stateful value is: {}", state.0) /// } /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite() /// .mount("/", routes![index]) /// .manage(MyValue(10)) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` @@ -795,13 +799,15 @@ impl Rocket { /// use rocket::Rocket; /// use rocket::fairing::AdHoc; /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite() /// .attach(AdHoc::on_launch("Launch Message", |_| { /// println!("Rocket is launching!"); /// })) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` @@ -863,15 +869,15 @@ impl Rocket { /// # Example /// /// ```rust - /// #[tokio::main] + /// #[rocket::main] /// async fn main() { /// # if false { - /// let result = rocket::ignite().launch(); + /// let result = rocket::ignite().launch().await; /// assert!(result.is_ok()); /// # } /// } /// ``` - async fn serve(self) -> Result<(), crate::error::Error> { + pub async fn launch(self) -> Result<(), crate::error::Error> { use std::net::ToSocketAddrs; use crate::error::Error::Launch; @@ -954,40 +960,6 @@ impl Rocket { server.await } - /// Starts the application server and begins listening for and dispatching - /// requests to mounted routes and catchers. This function does not return - /// unless a shutdown is requested via a [`ShutdownHandle`] or there is an - /// error. - /// - /// This is a convenience function that creates a suitable default runtime - /// and launches the server on that runtime. If you already have a runtime, - /// use the [`Rocket::serve`] method instead. - /// - /// # Error - /// - /// If there is a problem starting the application, a [`LaunchError`] is - /// returned. Note that a value of type `LaunchError` panics if dropped - /// without first being inspected. See the [`LaunchError`] documentation for - /// more information. - /// - /// # Example - /// - /// ```rust - /// # if false { - /// rocket::ignite().launch(); - /// # } - /// ``` - pub fn launch(self) -> Result<(), crate::error::Error> { - // Initialize the tokio runtime - let mut runtime = tokio::runtime::Builder::new() - .threaded_scheduler() - .enable_all() - .build() - .expect("Cannot build runtime!"); - - runtime.block_on(async move { self.serve().await }) - } - pub(crate) fn _manifest(&self) -> &Manifest { self.manifest.as_ref().expect("internal error: manifest was taken and not replaced. \ Was `inspect()` called but not polled to completion?") @@ -1079,7 +1051,7 @@ impl Manifest { /// }); /// /// // Shuts down after 10 seconds - /// let shutdown_result = rocket.launch(); + /// let shutdown_result = rocket.launch().await; /// assert!(shutdown_result.is_ok()); /// # } /// # }); @@ -1160,13 +1132,15 @@ impl Manifest { /// use rocket::Rocket; /// use rocket::fairing::AdHoc; /// - /// fn main() { + /// #[rocket::main] + /// async fn main() { /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite() /// .attach(AdHoc::on_launch("Config Printer", |manifest| { /// println!("Rocket launch config: {:?}", manifest.config()); /// })) - /// .launch(); + /// .launch() + /// .await; /// # } /// } /// ``` diff --git a/core/lib/src/shutdown.rs b/core/lib/src/shutdown.rs index 40f7c6d8..4a05d054 100644 --- a/core/lib/src/shutdown.rs +++ b/core/lib/src/shutdown.rs @@ -24,11 +24,13 @@ use tokio::sync::mpsc; /// "Shutting down..." /// } /// -/// fn main() { +/// #[rocket::main] +/// async fn main() { /// # if false { /// rocket::ignite() /// .mount("/", routes![shutdown]) /// .launch() +/// .await /// .expect("server failed unexpectedly"); /// # } /// } diff --git a/examples/config/src/main.rs b/examples/config/src/main.rs index b96db851..4f246302 100644 --- a/examples/config/src/main.rs +++ b/examples/config/src/main.rs @@ -1,4 +1,5 @@ // This example's illustration is the Rocket.toml file. -fn main() { - let _ = rocket::ignite().launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().launch().await; } diff --git a/examples/content_types/src/main.rs b/examples/content_types/src/main.rs index d0acebf9..777fc2e5 100644 --- a/examples/content_types/src/main.rs +++ b/examples/content_types/src/main.rs @@ -63,9 +63,10 @@ fn not_found(request: &Request<'_>) -> Html { Html(html) } -fn main() { +#[rocket::main] +async fn main() { let _ = rocket::ignite() .mount("/hello", routes![get_hello, post_hello]) .register(catchers![not_found]) - .launch(); + .launch().await; } diff --git a/examples/cookies/src/main.rs b/examples/cookies/src/main.rs index 2d4e84c2..6e669759 100644 --- a/examples/cookies/src/main.rs +++ b/examples/cookies/src/main.rs @@ -38,6 +38,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![submit, index]).attach(Template::fairing()) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/errors/src/main.rs b/examples/errors/src/main.rs index 8ad4bc35..228dc692 100644 --- a/examples/errors/src/main.rs +++ b/examples/errors/src/main.rs @@ -18,12 +18,13 @@ fn not_found(req: &rocket::Request<'_>) -> content::Html { req.uri())) } -fn main() { +#[rocket::main] +async fn main() { let result = rocket::ignite() // .mount("/", routes![hello, hello]) // uncoment this to get an error .mount("/", routes![hello]) .register(catchers![not_found]) - .launch(); + .launch().await; if let Err(e) = result { println!("Whoops! Rocket didn't launch!"); diff --git a/examples/fairings/src/main.rs b/examples/fairings/src/main.rs index 80978725..d810a72d 100644 --- a/examples/fairings/src/main.rs +++ b/examples/fairings/src/main.rs @@ -94,6 +94,7 @@ fn rocket() -> rocket::Rocket { })) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/form_kitchen_sink/src/main.rs b/examples/form_kitchen_sink/src/main.rs index 3ba791cb..bb6dcb05 100644 --- a/examples/form_kitchen_sink/src/main.rs +++ b/examples/form_kitchen_sink/src/main.rs @@ -45,6 +45,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![index, sink]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/form_validation/src/main.rs b/examples/form_validation/src/main.rs index 97e4dd36..6f179b6b 100644 --- a/examples/form_validation/src/main.rs +++ b/examples/form_validation/src/main.rs @@ -81,6 +81,7 @@ fn rocket() -> rocket::Rocket { .mount("/", routes![files::index, files::files, user_page, login]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/handlebars_templates/src/main.rs b/examples/handlebars_templates/src/main.rs index 46bd9d87..2595734e 100644 --- a/examples/handlebars_templates/src/main.rs +++ b/examples/handlebars_templates/src/main.rs @@ -77,6 +77,7 @@ fn rocket() -> rocket::Rocket { })) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/hello_2018/src/main.rs b/examples/hello_2018/src/main.rs index 1d4e967f..a61d9242 100644 --- a/examples/hello_2018/src/main.rs +++ b/examples/hello_2018/src/main.rs @@ -9,6 +9,7 @@ fn hello() -> &'static str { "Hello, Rust 2018!" } -fn main() { - let _ = rocket::ignite().mount("/", routes![hello]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![hello]).launch().await; } diff --git a/examples/hello_person/src/main.rs b/examples/hello_person/src/main.rs index 98fffdbf..d3321844 100644 --- a/examples/hello_person/src/main.rs +++ b/examples/hello_person/src/main.rs @@ -14,6 +14,7 @@ fn hi(name: String) -> String { name } -fn main() { - let _ = rocket::ignite().mount("/", routes![hello, hi]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![hello, hi]).launch().await; } diff --git a/examples/hello_world/src/main.rs b/examples/hello_world/src/main.rs index 1d2876fd..04ae994d 100644 --- a/examples/hello_world/src/main.rs +++ b/examples/hello_world/src/main.rs @@ -9,6 +9,7 @@ fn hello() -> &'static str { "Hello, world!" } -fn main() { - let _ = rocket::ignite().mount("/", routes![hello]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![hello]).launch().await; } diff --git a/examples/json/src/main.rs b/examples/json/src/main.rs index 13ef804f..9d2a8a9a 100644 --- a/examples/json/src/main.rs +++ b/examples/json/src/main.rs @@ -76,6 +76,7 @@ fn rocket() -> rocket::Rocket { .manage(Mutex::new(HashMap::::new())) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/managed_queue/src/main.rs b/examples/managed_queue/src/main.rs index ba58e1a3..595ec825 100644 --- a/examples/managed_queue/src/main.rs +++ b/examples/managed_queue/src/main.rs @@ -25,6 +25,7 @@ fn rocket() -> rocket::Rocket { .manage(LogChannel(SegQueue::new())) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/manual_routes/src/main.rs b/examples/manual_routes/src/main.rs index 6296a660..d5581632 100644 --- a/examples/manual_routes/src/main.rs +++ b/examples/manual_routes/src/main.rs @@ -118,6 +118,7 @@ fn rocket() -> rocket::Rocket { .register(vec![not_found_catcher]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/msgpack/src/main.rs b/examples/msgpack/src/main.rs index 14a0a1b1..3ef38e02 100644 --- a/examples/msgpack/src/main.rs +++ b/examples/msgpack/src/main.rs @@ -27,6 +27,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/message", routes![get, create]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/optional_redirect/src/main.rs b/examples/optional_redirect/src/main.rs index 3287db12..cf821b62 100644 --- a/examples/optional_redirect/src/main.rs +++ b/examples/optional_redirect/src/main.rs @@ -26,6 +26,7 @@ fn login() -> &'static str { "Hi! That user doesn't exist. Maybe you need to log in?" } -fn main() { - let _ = rocket::ignite().mount("/", routes![root, user, login]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![root, user, login]).launch().await; } diff --git a/examples/pastebin/src/main.rs b/examples/pastebin/src/main.rs index 70afb0fd..a0b8ce15 100644 --- a/examples/pastebin/src/main.rs +++ b/examples/pastebin/src/main.rs @@ -55,6 +55,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![index, upload, retrieve]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/query_params/src/main.rs b/examples/query_params/src/main.rs index 4a8dae9c..9ee23e6b 100644 --- a/examples/query_params/src/main.rs +++ b/examples/query_params/src/main.rs @@ -36,6 +36,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![hello, hello_20]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/ranking/src/main.rs b/examples/ranking/src/main.rs index d92eea57..f2844d34 100644 --- a/examples/ranking/src/main.rs +++ b/examples/ranking/src/main.rs @@ -16,6 +16,7 @@ fn hi(name: String, age: &RawStr) -> String { format!("Hi {}! Your age ({}) is kind of funky.", name, age) } -fn main() { - let _ = rocket::ignite().mount("/", routes![hi, hello]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![hi, hello]).launch().await; } diff --git a/examples/raw_sqlite/src/main.rs b/examples/raw_sqlite/src/main.rs index 242f6c11..d7e3dc93 100644 --- a/examples/raw_sqlite/src/main.rs +++ b/examples/raw_sqlite/src/main.rs @@ -48,6 +48,7 @@ fn rocket() -> Rocket { .mount("/", routes![hello]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/raw_upload/src/main.rs b/examples/raw_upload/src/main.rs index 45ed8968..0c717895 100644 --- a/examples/raw_upload/src/main.rs +++ b/examples/raw_upload/src/main.rs @@ -21,6 +21,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![index, upload]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/redirect/src/main.rs b/examples/redirect/src/main.rs index 31b00e6a..82905a80 100644 --- a/examples/redirect/src/main.rs +++ b/examples/redirect/src/main.rs @@ -16,6 +16,7 @@ fn login() -> &'static str { "Hi! Please log in before continuing." } -fn main() { - let _ = rocket::ignite().mount("/", routes![root, login]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![root, login]).launch().await; } diff --git a/examples/request_guard/src/main.rs b/examples/request_guard/src/main.rs index 84fd32c6..7e17fad9 100644 --- a/examples/request_guard/src/main.rs +++ b/examples/request_guard/src/main.rs @@ -26,8 +26,9 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![header_count]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } #[cfg(test)] diff --git a/examples/request_local_state/src/main.rs b/examples/request_local_state/src/main.rs index 55678d27..db29bad8 100644 --- a/examples/request_local_state/src/main.rs +++ b/examples/request_local_state/src/main.rs @@ -84,6 +84,7 @@ fn rocket() -> rocket::Rocket { .mount("/", routes![r_sync, r_async]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/session/src/main.rs b/examples/session/src/main.rs index bc1007bd..2ee4cf25 100644 --- a/examples/session/src/main.rs +++ b/examples/session/src/main.rs @@ -86,6 +86,7 @@ fn rocket() -> rocket::Rocket { .mount("/", routes![index, user_index, login, logout, login_user, login_page]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/state/src/main.rs b/examples/state/src/main.rs index 3f08df30..8d62f839 100644 --- a/examples/state/src/main.rs +++ b/examples/state/src/main.rs @@ -30,6 +30,7 @@ fn rocket() -> rocket::Rocket { .manage(HitCount(AtomicUsize::new(0))) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/static_files/src/main.rs b/examples/static_files/src/main.rs index 921d6f95..767d1835 100644 --- a/examples/static_files/src/main.rs +++ b/examples/static_files/src/main.rs @@ -9,6 +9,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", StaticFiles::from("static")) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/stream/src/main.rs b/examples/stream/src/main.rs index 939b5a28..860f82d8 100644 --- a/examples/stream/src/main.rs +++ b/examples/stream/src/main.rs @@ -26,6 +26,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![root, file]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/tera_templates/src/main.rs b/examples/tera_templates/src/main.rs index cdd8490c..2970e04a 100644 --- a/examples/tera_templates/src/main.rs +++ b/examples/tera_templates/src/main.rs @@ -42,6 +42,7 @@ fn rocket() -> rocket::Rocket { .register(catchers![not_found]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/testing/src/main.rs b/examples/testing/src/main.rs index 39af935c..a6f297d0 100644 --- a/examples/testing/src/main.rs +++ b/examples/testing/src/main.rs @@ -11,8 +11,9 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![hello]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } #[cfg(test)] diff --git a/examples/tls/src/main.rs b/examples/tls/src/main.rs index 1d2876fd..04ae994d 100644 --- a/examples/tls/src/main.rs +++ b/examples/tls/src/main.rs @@ -9,6 +9,7 @@ fn hello() -> &'static str { "Hello, world!" } -fn main() { - let _ = rocket::ignite().mount("/", routes![hello]).launch(); +#[rocket::main] +async fn main() { + let _ = rocket::ignite().mount("/", routes![hello]).launch().await; } diff --git a/examples/todo/src/main.rs b/examples/todo/src/main.rs index 9421b501..08c41641 100644 --- a/examples/todo/src/main.rs +++ b/examples/todo/src/main.rs @@ -114,6 +114,7 @@ fn rocket() -> Rocket { .attach(Template::fairing()) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/examples/uuid/src/main.rs b/examples/uuid/src/main.rs index 04dbe0c1..6a853df4 100644 --- a/examples/uuid/src/main.rs +++ b/examples/uuid/src/main.rs @@ -37,6 +37,7 @@ fn rocket() -> rocket::Rocket { rocket::ignite().mount("/", routes![people]) } -fn main() { - let _ = rocket().launch(); +#[rocket::main] +async fn main() { + let _ = rocket().launch().await; } diff --git a/site/guide/3-overview.md b/site/guide/3-overview.md index e915f2f4..4ca13caa 100644 --- a/site/guide/3-overview.md +++ b/site/guide/3-overview.md @@ -238,9 +238,9 @@ You can find async-ready libraries on [crates.io](https://crates.io) with the ! note - Rocket 0.5 uses the tokio (0.2) runtime. `Rocket::launch()` will automatically - start a runtime for you, or you can create a runtime yourself and use - `Rocket::spawn()`. + Rocket 0.5 uses the tokio (0.2) runtime. The runtime is started for you + if you use `#[rocket::main]`, but you can still `launch()` a rocket + instance on a custom-built `Runtime`. ### Cooperative Multitasking