rocket/lib.rs
1#![recursion_limit="256"]
2
3#![doc(html_root_url = "https://api.rocket.rs/master")]
4#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
5#![doc(html_logo_url = "https://rocket.rs/images/logo-boxed.png")]
6#![cfg_attr(nightly, feature(doc_cfg))]
7#![cfg_attr(nightly, feature(decl_macro))]
8
9//! # Rocket - Core API Documentation
10//!
11//! Hello, and welcome to the core Rocket API documentation!
12//!
13//! This API documentation is highly technical and is purely a reference.
14//! There's an [overview] of Rocket on the main site as well as a [full,
15//! detailed guide]. If you'd like pointers on getting started, see the
16//! [quickstart] or [getting started] chapters of the guide.
17//!
18//! [overview]: https://rocket.rs/master/overview
19//! [full, detailed guide]: https://rocket.rs/master/guide
20//! [quickstart]: https://rocket.rs/master/guide/quickstart
21//! [getting started]: https://rocket.rs/master/guide/getting-started
22//!
23//! ## Usage
24//!
25//! Depend on `rocket` in `Cargo.toml`:
26//!
27//! ```toml
28//! [dependencies]
29//! rocket = "0.6.0-dev"
30//! ```
31//!
32//! <small>Note that development versions, tagged with `-dev`, are not published
33//! and need to be specified as [git dependencies].</small>
34//!
35//! See the [guide](https://rocket.rs/master/guide) for more information on how
36//! to write Rocket applications. Here's a simple example to get you started:
37//!
38//! [git dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories
39//!
40//! ```rust,no_run
41//! #[macro_use] extern crate rocket;
42//!
43//! #[get("/")]
44//! fn hello() -> &'static str {
45//! "Hello, world!"
46//! }
47//!
48//! #[launch]
49//! fn rocket() -> _ {
50//! rocket::build().mount("/", routes![hello])
51//! }
52//! ```
53//!
54//! ## Features
55//!
56//! To avoid compiling unused dependencies, Rocket feature-gates optional
57//! functionality, some enabled by default:
58//!
59//! | Feature | Default? | Description |
60//! |-----------------|----------|---------------------------------------------------------|
61//! | `trace` | Yes | Enables the default Rocket tracing [subscriber]. |
62//! | `http2` | Yes | Support for HTTP/2 (enabled by default). |
63//! | `secrets` | No | Support for authenticated, encrypted [private cookies]. |
64//! | `tls` | No | Support for [TLS] encrypted connections. |
65//! | `mtls` | No | Support for verified clients via [mutual TLS]. |
66//! | `json` | No | Support for [JSON (de)serialization]. |
67//! | `msgpack` | No | Support for [MessagePack (de)serialization]. |
68//! | `uuid` | No | Support for [UUID value parsing and (de)serialization]. |
69//! | `tokio-macros` | No | Enables the `macros` feature in the exported `tokio` |
70//! | `http3-preview` | No | Experimental preview support for [HTTP/3]. |
71//!
72//! Disabled features can be selectively enabled in `Cargo.toml`:
73//!
74//! ```toml
75//! [dependencies]
76//! rocket = { version = "0.6.0-dev", features = ["secrets", "tls", "json"] }
77//! ```
78//!
79//! Conversely, HTTP/2 can be disabled:
80//!
81//! ```toml
82//! [dependencies]
83//! rocket = { version = "0.6.0-dev", default-features = false }
84//! ```
85//!
86//! [subscriber]: crate::trace::subscriber
87//! [JSON (de)serialization]: crate::serde::json
88//! [MessagePack (de)serialization]: crate::serde::msgpack
89//! [UUID value parsing and (de)serialization]: crate::serde::uuid
90//! [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies
91//! [TLS]: https://rocket.rs/master/guide/configuration/#tls
92//! [mutual TLS]: crate::mtls
93//! [HTTP/3]: crate::listener::quic
94//!
95//! ## Configuration
96//!
97//! Rocket offers a rich, extensible configuration system built on [Figment]. By
98//! default, Rocket applications are configured via a `Rocket.toml` file
99//! and/or `ROCKET_{PARAM}` environment variables, but applications may
100//! configure their own sources. See the [configuration guide] for full details.
101//!
102//! ## Testing
103//!
104//! The [`local`] module contains structures that facilitate unit and
105//! integration testing of a Rocket application. The top-level [`local`] module
106//! documentation and the [testing guide] include detailed examples.
107//!
108//! [configuration guide]: https://rocket.rs/master/guide/configuration/
109//! [testing guide]: https://rocket.rs/master/guide/testing/#testing
110//! [Figment]: https://docs.rs/figment
111
112// Allows using Rocket's codegen in Rocket itself.
113extern crate self as rocket;
114
115/// These are public dependencies! Update docs if these are changed, especially
116/// figment's version number in docs.
117#[doc(hidden)]
118pub use yansi;
119#[doc(hidden)]
120pub use async_stream;
121pub use futures;
122pub use tokio;
123pub use figment;
124pub use time;
125pub use tracing;
126pub use either;
127
128#[macro_use]
129pub mod trace;
130#[macro_use]
131pub mod outcome;
132#[macro_use]
133pub mod data;
134#[doc(hidden)]
135pub mod sentinel;
136pub mod local;
137pub mod request;
138pub mod response;
139pub mod config;
140pub mod form;
141pub mod fairing;
142pub mod error;
143pub mod catcher;
144pub mod route;
145pub mod serde;
146pub mod shield;
147pub mod fs;
148pub mod http;
149pub mod listener;
150pub mod shutdown;
151#[cfg(feature = "tls")]
152#[cfg_attr(nightly, doc(cfg(feature = "tls")))]
153pub mod tls;
154#[cfg(feature = "mtls")]
155#[cfg_attr(nightly, doc(cfg(feature = "mtls")))]
156pub mod mtls;
157
158#[path = "rocket.rs"]
159mod rkt;
160mod util;
161mod server;
162mod lifecycle;
163mod state;
164mod router;
165mod phase;
166mod erased;
167
168#[doc(inline)] pub use rocket_codegen::*;
169
170#[doc(inline)] pub use crate::response::Response;
171#[doc(inline)] pub use crate::data::Data;
172#[doc(inline)] pub use crate::config::Config;
173#[doc(inline)] pub use crate::catcher::Catcher;
174#[doc(inline)] pub use crate::route::Route;
175#[doc(inline)] pub use crate::phase::{Phase, Build, Ignite, Orbit};
176#[doc(inline)] pub use crate::error::Error;
177#[doc(inline)] pub use crate::sentinel::{Sentinel, Sentry};
178#[doc(inline)] pub use crate::request::Request;
179#[doc(inline)] pub use crate::rkt::Rocket;
180#[doc(inline)] pub use crate::shutdown::Shutdown;
181#[doc(inline)] pub use crate::state::State;
182
183/// Retrofits support for `async fn` in trait impls and declarations.
184///
185/// Any trait declaration or trait `impl` decorated with `#[async_trait]` is
186/// retrofitted with support for `async fn`s:
187///
188/// ```rust
189/// # use rocket::*;
190/// #[async_trait]
191/// trait MyAsyncTrait {
192/// async fn do_async_work();
193/// }
194///
195/// #[async_trait]
196/// impl MyAsyncTrait for () {
197/// async fn do_async_work() { /* .. */ }
198/// }
199/// ```
200///
201/// All `impl`s for a trait declared with `#[async_trait]` must themselves be
202/// decorated with `#[async_trait]`. Many of Rocket's traits, such as
203/// [`FromRequest`](crate::request::FromRequest) and
204/// [`Fairing`](crate::fairing::Fairing) are `async`. As such, implementations
205/// of said traits must be decorated with `#[async_trait]`. See the individual
206/// trait docs for trait-specific details.
207///
208/// For more details on `#[async_trait]`, see [`async_trait`](mod@async_trait).
209#[doc(inline)]
210pub use async_trait::async_trait;
211
212const WORKER_PREFIX: &str = "rocket-worker";
213
214/// Creates a [`Rocket`] instance with the default config provider: aliases
215/// [`Rocket::build()`].
216pub fn build() -> Rocket<Build> {
217 Rocket::build()
218}
219
220/// Creates a [`Rocket`] instance with a custom config provider: aliases
221/// [`Rocket::custom()`].
222pub fn custom<T: figment::Provider>(provider: T) -> Rocket<Build> {
223 Rocket::custom(provider)
224}
225
226/// WARNING: This is unstable! Do not use this method outside of Rocket!
227#[doc(hidden)]
228pub fn async_run<F, R>(fut: F, workers: usize, sync: usize, force_end: bool, name: &str) -> R
229 where F: std::future::Future<Output = R>
230{
231 let runtime = tokio::runtime::Builder::new_multi_thread()
232 .thread_name(name)
233 .worker_threads(workers)
234 .max_blocking_threads(sync)
235 .enable_all()
236 .build()
237 .expect("create tokio runtime");
238
239 let result = runtime.block_on(fut);
240 if force_end {
241 runtime.shutdown_timeout(std::time::Duration::from_millis(500));
242 }
243
244 result
245}
246
247/// WARNING: This is unstable! Do not use this method outside of Rocket!
248#[doc(hidden)]
249pub fn async_test<R>(fut: impl std::future::Future<Output = R>) -> R {
250 async_run(fut, 1, 32, true, &format!("{WORKER_PREFIX}-test-thread"))
251}
252
253/// WARNING: This is unstable! Do not use this method outside of Rocket!
254#[doc(hidden)]
255pub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {
256 fn bail<T, E: crate::trace::Trace>(e: E) -> T {
257 e.trace_error();
258 panic!("aborting due to error")
259 }
260
261 // FIXME: We need to run `fut` to get the user's `Figment` to properly set
262 // up the async env, but we need the async env to run `fut`. So we're stuck.
263 // Tokio doesn't let us take the state from one async env and migrate it to
264 // another, so we need to use one, making this impossible.
265 //
266 // So as a result, we only use values from Rocket's figment. These
267 // values won't reflect swaps of `Rocket` in attach fairings with different
268 // config values, or values from non-Rocket configs. See tokio-rs/tokio#3329
269 // for a necessary resolution in `tokio`.
270 let fig = Config::figment();
271 let workers = fig.extract_inner(Config::WORKERS).unwrap_or_else(bail);
272 let max_blocking = fig.extract_inner(Config::MAX_BLOCKING).unwrap_or_else(bail);
273 let force = fig.focus(Config::SHUTDOWN).extract_inner("force").unwrap_or_else(bail);
274 async_run(fut, workers, max_blocking, force, &format!("{WORKER_PREFIX}-thread"))
275}
276
277/// Executes a `future` to completion on a new tokio-based Rocket async runtime.
278///
279/// The runtime is terminated on shutdown, and the future's resolved value is
280/// returned.
281///
282/// # Considerations
283///
284/// This function is a low-level mechanism intended to be used to execute the
285/// future returned by [`Rocket::launch()`] in a self-contained async runtime
286/// designed for Rocket. It runs futures in exactly the same manner as
287/// [`#[launch]`](crate::launch) and [`#[main]`](crate::main) do and is thus
288/// _never_ the preferred mechanism for running a Rocket application. _Always_
289/// prefer to use the [`#[launch]`](crate::launch) or [`#[main]`](crate::main)
290/// attributes. For example [`#[main]`](crate::main) can be used even when
291/// Rocket is just a small part of a bigger application:
292///
293/// ```rust,no_run
294/// #[rocket::main]
295/// async fn main() {
296/// # let should_start_server_in_foreground = false;
297/// # let should_start_server_in_background = false;
298/// let rocket = rocket::build();
299/// if should_start_server_in_foreground {
300/// rocket::build().launch().await;
301/// } else if should_start_server_in_background {
302/// rocket::tokio::spawn(rocket.launch());
303/// } else {
304/// // do something else
305/// }
306/// }
307/// ```
308///
309/// See [Rocket#launching] for more on using these attributes.
310///
311/// # Example
312///
313/// Build an instance of Rocket, launch it, and wait for shutdown:
314///
315/// ```rust,no_run
316/// use rocket::fairing::AdHoc;
317///
318/// let rocket = rocket::build()
319/// .attach(AdHoc::on_liftoff("Liftoff Printer", |_| Box::pin(async move {
320/// println!("Stalling liftoff for a second...");
321/// rocket::tokio::time::sleep(std::time::Duration::from_secs(1)).await;
322/// println!("And we're off!");
323/// })));
324///
325/// rocket::execute(rocket.launch());
326/// ```
327///
328/// Launch a pre-built instance of Rocket and wait for it to shutdown:
329///
330/// ```rust,no_run
331/// use rocket::{Rocket, Ignite, Phase, Error};
332///
333/// fn launch<P: Phase>(rocket: Rocket<P>) -> Result<Rocket<Ignite>, Error> {
334/// rocket::execute(rocket.launch())
335/// }
336/// ```
337///
338/// Do async work to build an instance of Rocket, launch, and wait for shutdown:
339///
340/// ```rust,no_run
341/// use rocket::fairing::AdHoc;
342///
343/// // This line can also be inside of the `async` block.
344/// let rocket = rocket::build();
345///
346/// rocket::execute(async move {
347/// let rocket = rocket.ignite().await?;
348/// let config = rocket.config();
349/// rocket.launch().await
350/// });
351/// ```
352pub fn execute<R, F>(future: F) -> R
353 where F: std::future::Future<Output = R> + Send
354{
355 async_main(future)
356}
357
358/// Returns a future that evaluates to `true` exactly when there is a presently
359/// running tokio async runtime that was likely started by Rocket.
360fn running_within_rocket_async_rt() -> impl std::future::Future<Output = bool> {
361 use futures::FutureExt;
362
363 tokio::task::spawn_blocking(|| {
364 let this = std::thread::current();
365 this.name().map_or(false, |s| s.starts_with(WORKER_PREFIX))
366 }).map(|r| r.unwrap_or(false))
367}