mirror of
https://github.com/SergioBenitez/Rocket.git
synced 2026-02-06 10:48:05 +00:00
This commit complete the migration to 'tracing' for all logging. Below
is a summary of all relevant commits, including this one:
Log improvements:
- All log (trace) messages are structured which means they contain fields
that can formatted by any subscriber.
- Logging can be disabled entirely by disabling the default `trace` feature.
- Routes and catchers now contain location (file/line) information.
- Two log format kinds: pretty and compact via ROCKET_LOG_FORMAT
- Coloring is not disabled globally. Thus applications can color even if
Rocket is configured not to.
- Rocket is more conservative about 'warn' and 'error' messages, reserving
those log levels for messages useful in production.
- Errors from guards logged by codegen now use the 'Display' implementation of
those errors when one exists.
- Secrets are never logged, even when directly asked for.
New features:
- Many Rocket types know how to trace themselves via a new `Trace` trait.
- `Either` types can now be used in `uri!()` calls.
- A `RequestIdLayer` tags all requests with a unique ID.
Breaking changes to configuration:
- `Config::log_level` is of type `Option<Level>`. `None` disables tracing.
- `log_level` now uses the traditional log level names: "off", "error",
"warn", "info", "debug", "trace", or 0-5. This replace the Rocket-specific
"normal", "debug", "critical".
- A new option, `log_format`, which is either `compact` or `pretty`,
determines how Rocket's tracing subscriber log trace messages.
Breaking changes:
- Hidden `rocket::Either` is now publicly available at `rocket::either::Either`.
- `rocket::Error` no longer panics when dropped.
- `main` generated by `#[launch]` returns an `ExitCode`.
- `FromParam` `Err` now always returns the actual error as opposed to the
string that failed to parse. To recover the original string, use `Either<T,
&str>`, where `T: FromParam`, as a parameter guard.
- Many types that implemented `Display` now instead implement `Trace`.
- `Error::pretty_print()` was removed. Use `Error::trace()` via `Trace` impl.
Internal improvements:
- Made more space in CI machines for tasks.
- Cleaned up testbench code using `inventory`.
Resolves #21.
368 lines
12 KiB
Rust
368 lines
12 KiB
Rust
#![recursion_limit="256"]
|
|
|
|
#![doc(html_root_url = "https://api.rocket.rs/master")]
|
|
#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
|
|
#![doc(html_logo_url = "https://rocket.rs/images/logo-boxed.png")]
|
|
#![cfg_attr(nightly, feature(doc_cfg))]
|
|
#![cfg_attr(nightly, feature(decl_macro))]
|
|
|
|
//! # Rocket - Core API Documentation
|
|
//!
|
|
//! Hello, and welcome to the core Rocket API documentation!
|
|
//!
|
|
//! This API documentation is highly technical and is purely a reference.
|
|
//! There's an [overview] of Rocket on the main site as well as a [full,
|
|
//! detailed guide]. If you'd like pointers on getting started, see the
|
|
//! [quickstart] or [getting started] chapters of the guide.
|
|
//!
|
|
//! [overview]: https://rocket.rs/master/overview
|
|
//! [full, detailed guide]: https://rocket.rs/master/guide
|
|
//! [quickstart]: https://rocket.rs/master/guide/quickstart
|
|
//! [getting started]: https://rocket.rs/master/guide/getting-started
|
|
//!
|
|
//! ## Usage
|
|
//!
|
|
//! Depend on `rocket` in `Cargo.toml`:
|
|
//!
|
|
//! ```toml
|
|
//! [dependencies]
|
|
//! rocket = "0.6.0-dev"
|
|
//! ```
|
|
//!
|
|
//! <small>Note that development versions, tagged with `-dev`, are not published
|
|
//! and need to be specified as [git dependencies].</small>
|
|
//!
|
|
//! See the [guide](https://rocket.rs/master/guide) for more information on how
|
|
//! to write Rocket applications. Here's a simple example to get you started:
|
|
//!
|
|
//! [git dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories
|
|
//!
|
|
//! ```rust,no_run
|
|
//! #[macro_use] extern crate rocket;
|
|
//!
|
|
//! #[get("/")]
|
|
//! fn hello() -> &'static str {
|
|
//! "Hello, world!"
|
|
//! }
|
|
//!
|
|
//! #[launch]
|
|
//! fn rocket() -> _ {
|
|
//! rocket::build().mount("/", routes![hello])
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! ## Features
|
|
//!
|
|
//! To avoid compiling unused dependencies, Rocket feature-gates optional
|
|
//! functionality, some enabled by default:
|
|
//!
|
|
//! | Feature | Default? | Description |
|
|
//! |-----------------|----------|---------------------------------------------------------|
|
|
//! | `trace` | Yes | Enables the default Rocket tracing [subscriber]. |
|
|
//! | `http2` | Yes | Support for HTTP/2 (enabled by default). |
|
|
//! | `secrets` | No | Support for authenticated, encrypted [private cookies]. |
|
|
//! | `tls` | No | Support for [TLS] encrypted connections. |
|
|
//! | `mtls` | No | Support for verified clients via [mutual TLS]. |
|
|
//! | `json` | No | Support for [JSON (de)serialization]. |
|
|
//! | `msgpack` | No | Support for [MessagePack (de)serialization]. |
|
|
//! | `uuid` | No | Support for [UUID value parsing and (de)serialization]. |
|
|
//! | `tokio-macros` | No | Enables the `macros` feature in the exported `tokio` |
|
|
//! | `http3-preview` | No | Experimental preview support for [HTTP/3]. |
|
|
//!
|
|
//! Disabled features can be selectively enabled in `Cargo.toml`:
|
|
//!
|
|
//! ```toml
|
|
//! [dependencies]
|
|
//! rocket = { version = "0.6.0-dev", features = ["secrets", "tls", "json"] }
|
|
//! ```
|
|
//!
|
|
//! Conversely, HTTP/2 can be disabled:
|
|
//!
|
|
//! ```toml
|
|
//! [dependencies]
|
|
//! rocket = { version = "0.6.0-dev", default-features = false }
|
|
//! ```
|
|
//!
|
|
//! [subscriber]: crate::trace::subscriber
|
|
//! [JSON (de)serialization]: crate::serde::json
|
|
//! [MessagePack (de)serialization]: crate::serde::msgpack
|
|
//! [UUID value parsing and (de)serialization]: crate::serde::uuid
|
|
//! [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies
|
|
//! [TLS]: https://rocket.rs/master/guide/configuration/#tls
|
|
//! [mutual TLS]: crate::mtls
|
|
//! [HTTP/3]: crate::listener::quic
|
|
//!
|
|
//! ## Configuration
|
|
//!
|
|
//! Rocket offers a rich, extensible configuration system built on [Figment]. By
|
|
//! default, Rocket applications are configured via a `Rocket.toml` file
|
|
//! and/or `ROCKET_{PARAM}` environment variables, but applications may
|
|
//! configure their own sources. See the [configuration guide] for full details.
|
|
//!
|
|
//! ## Testing
|
|
//!
|
|
//! The [`local`] module contains structures that facilitate unit and
|
|
//! integration testing of a Rocket application. The top-level [`local`] module
|
|
//! documentation and the [testing guide] include detailed examples.
|
|
//!
|
|
//! [configuration guide]: https://rocket.rs/master/guide/configuration/
|
|
//! [testing guide]: https://rocket.rs/master/guide/testing/#testing
|
|
//! [Figment]: https://docs.rs/figment
|
|
|
|
// Allows using Rocket's codegen in Rocket itself.
|
|
extern crate self as rocket;
|
|
|
|
/// These are public dependencies! Update docs if these are changed, especially
|
|
/// figment's version number in docs.
|
|
#[doc(hidden)]
|
|
pub use yansi;
|
|
#[doc(hidden)]
|
|
pub use async_stream;
|
|
pub use futures;
|
|
pub use tokio;
|
|
pub use figment;
|
|
pub use time;
|
|
pub use tracing;
|
|
pub use either;
|
|
|
|
#[macro_use]
|
|
pub mod trace;
|
|
#[macro_use]
|
|
pub mod outcome;
|
|
#[macro_use]
|
|
pub mod data;
|
|
#[doc(hidden)]
|
|
pub mod sentinel;
|
|
pub mod local;
|
|
pub mod request;
|
|
pub mod response;
|
|
pub mod config;
|
|
pub mod form;
|
|
pub mod fairing;
|
|
pub mod error;
|
|
pub mod catcher;
|
|
pub mod route;
|
|
pub mod serde;
|
|
pub mod shield;
|
|
pub mod fs;
|
|
pub mod http;
|
|
pub mod listener;
|
|
pub mod shutdown;
|
|
#[cfg(feature = "tls")]
|
|
#[cfg_attr(nightly, doc(cfg(feature = "tls")))]
|
|
pub mod tls;
|
|
#[cfg(feature = "mtls")]
|
|
#[cfg_attr(nightly, doc(cfg(feature = "mtls")))]
|
|
pub mod mtls;
|
|
|
|
#[path = "rocket.rs"]
|
|
mod rkt;
|
|
mod util;
|
|
mod server;
|
|
mod lifecycle;
|
|
mod state;
|
|
mod router;
|
|
mod phase;
|
|
mod erased;
|
|
|
|
#[doc(inline)] pub use rocket_codegen::*;
|
|
|
|
#[doc(inline)] pub use crate::response::Response;
|
|
#[doc(inline)] pub use crate::data::Data;
|
|
#[doc(inline)] pub use crate::config::Config;
|
|
#[doc(inline)] pub use crate::catcher::Catcher;
|
|
#[doc(inline)] pub use crate::route::Route;
|
|
#[doc(inline)] pub use crate::phase::{Phase, Build, Ignite, Orbit};
|
|
#[doc(inline)] pub use crate::error::Error;
|
|
#[doc(inline)] pub use crate::sentinel::Sentinel;
|
|
#[doc(inline)] pub use crate::request::Request;
|
|
#[doc(inline)] pub use crate::rkt::Rocket;
|
|
#[doc(inline)] pub use crate::shutdown::Shutdown;
|
|
#[doc(inline)] pub use crate::state::State;
|
|
|
|
/// Retrofits support for `async fn` in trait impls and declarations.
|
|
///
|
|
/// Any trait declaration or trait `impl` decorated with `#[async_trait]` is
|
|
/// retrofitted with support for `async fn`s:
|
|
///
|
|
/// ```rust
|
|
/// # use rocket::*;
|
|
/// #[async_trait]
|
|
/// trait MyAsyncTrait {
|
|
/// async fn do_async_work();
|
|
/// }
|
|
///
|
|
/// #[async_trait]
|
|
/// impl MyAsyncTrait for () {
|
|
/// async fn do_async_work() { /* .. */ }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// All `impl`s for a trait declared with `#[async_trait]` must themselves be
|
|
/// decorated with `#[async_trait]`. Many of Rocket's traits, such as
|
|
/// [`FromRequest`](crate::request::FromRequest) and
|
|
/// [`Fairing`](crate::fairing::Fairing) are `async`. As such, implementations
|
|
/// of said traits must be decorated with `#[async_trait]`. See the individual
|
|
/// trait docs for trait-specific details.
|
|
///
|
|
/// For more details on `#[async_trait]`, see [`async_trait`](mod@async_trait).
|
|
#[doc(inline)]
|
|
pub use async_trait::async_trait;
|
|
|
|
const WORKER_PREFIX: &str = "rocket-worker";
|
|
|
|
/// Creates a [`Rocket`] instance with the default config provider: aliases
|
|
/// [`Rocket::build()`].
|
|
pub fn build() -> Rocket<Build> {
|
|
Rocket::build()
|
|
}
|
|
|
|
/// Creates a [`Rocket`] instance with a custom config provider: aliases
|
|
/// [`Rocket::custom()`].
|
|
pub fn custom<T: figment::Provider>(provider: T) -> Rocket<Build> {
|
|
Rocket::custom(provider)
|
|
}
|
|
|
|
/// WARNING: This is unstable! Do not use this method outside of Rocket!
|
|
#[doc(hidden)]
|
|
pub fn async_run<F, R>(fut: F, workers: usize, sync: usize, force_end: bool, name: &str) -> R
|
|
where F: std::future::Future<Output = R>
|
|
{
|
|
let runtime = tokio::runtime::Builder::new_multi_thread()
|
|
.thread_name(name)
|
|
.worker_threads(workers)
|
|
.max_blocking_threads(sync)
|
|
.enable_all()
|
|
.build()
|
|
.expect("create tokio runtime");
|
|
|
|
let result = runtime.block_on(fut);
|
|
if force_end {
|
|
runtime.shutdown_timeout(std::time::Duration::from_millis(500));
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
/// WARNING: This is unstable! Do not use this method outside of Rocket!
|
|
#[doc(hidden)]
|
|
pub fn async_test<R>(fut: impl std::future::Future<Output = R>) -> R {
|
|
async_run(fut, 1, 32, true, &format!("{WORKER_PREFIX}-test-thread"))
|
|
}
|
|
|
|
/// WARNING: This is unstable! Do not use this method outside of Rocket!
|
|
#[doc(hidden)]
|
|
pub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {
|
|
fn bail<T, E: crate::trace::Trace>(e: E) -> T {
|
|
e.trace_error();
|
|
panic!("aborting due to error")
|
|
}
|
|
|
|
// FIXME: We need to run `fut` to get the user's `Figment` to properly set
|
|
// up the async env, but we need the async env to run `fut`. So we're stuck.
|
|
// Tokio doesn't let us take the state from one async env and migrate it to
|
|
// another, so we need to use one, making this impossible.
|
|
//
|
|
// So as a result, we only use values from Rocket's figment. These
|
|
// values won't reflect swaps of `Rocket` in attach fairings with different
|
|
// config values, or values from non-Rocket configs. See tokio-rs/tokio#3329
|
|
// for a necessary resolution in `tokio`.
|
|
let fig = Config::figment();
|
|
let workers = fig.extract_inner(Config::WORKERS).unwrap_or_else(bail);
|
|
let max_blocking = fig.extract_inner(Config::MAX_BLOCKING).unwrap_or_else(bail);
|
|
let force = fig.focus(Config::SHUTDOWN).extract_inner("force").unwrap_or_else(bail);
|
|
async_run(fut, workers, max_blocking, force, &format!("{WORKER_PREFIX}-thread"))
|
|
}
|
|
|
|
/// Executes a `future` to completion on a new tokio-based Rocket async runtime.
|
|
///
|
|
/// The runtime is terminated on shutdown, and the future's resolved value is
|
|
/// returned.
|
|
///
|
|
/// # Considerations
|
|
///
|
|
/// This function is a low-level mechanism intended to be used to execute the
|
|
/// future returned by [`Rocket::launch()`] in a self-contained async runtime
|
|
/// designed for Rocket. It runs futures in exactly the same manner as
|
|
/// [`#[launch]`](crate::launch) and [`#[main]`](crate::main) do and is thus
|
|
/// _never_ the preferred mechanism for running a Rocket application. _Always_
|
|
/// prefer to use the [`#[launch]`](crate::launch) or [`#[main]`](crate::main)
|
|
/// attributes. For example [`#[main]`](crate::main) can be used even when
|
|
/// Rocket is just a small part of a bigger application:
|
|
///
|
|
/// ```rust,no_run
|
|
/// #[rocket::main]
|
|
/// async fn main() {
|
|
/// # let should_start_server_in_foreground = false;
|
|
/// # let should_start_server_in_background = false;
|
|
/// let rocket = rocket::build();
|
|
/// if should_start_server_in_foreground {
|
|
/// rocket::build().launch().await;
|
|
/// } else if should_start_server_in_background {
|
|
/// rocket::tokio::spawn(rocket.launch());
|
|
/// } else {
|
|
/// // do something else
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// See [Rocket#launching] for more on using these attributes.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// Build an instance of Rocket, launch it, and wait for shutdown:
|
|
///
|
|
/// ```rust,no_run
|
|
/// use rocket::fairing::AdHoc;
|
|
///
|
|
/// let rocket = rocket::build()
|
|
/// .attach(AdHoc::on_liftoff("Liftoff Printer", |_| Box::pin(async move {
|
|
/// println!("Stalling liftoff for a second...");
|
|
/// rocket::tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
|
/// println!("And we're off!");
|
|
/// })));
|
|
///
|
|
/// rocket::execute(rocket.launch());
|
|
/// ```
|
|
///
|
|
/// Launch a pre-built instance of Rocket and wait for it to shutdown:
|
|
///
|
|
/// ```rust,no_run
|
|
/// use rocket::{Rocket, Ignite, Phase, Error};
|
|
///
|
|
/// fn launch<P: Phase>(rocket: Rocket<P>) -> Result<Rocket<Ignite>, Error> {
|
|
/// rocket::execute(rocket.launch())
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Do async work to build an instance of Rocket, launch, and wait for shutdown:
|
|
///
|
|
/// ```rust,no_run
|
|
/// use rocket::fairing::AdHoc;
|
|
///
|
|
/// // This line can also be inside of the `async` block.
|
|
/// let rocket = rocket::build();
|
|
///
|
|
/// rocket::execute(async move {
|
|
/// let rocket = rocket.ignite().await?;
|
|
/// let config = rocket.config();
|
|
/// rocket.launch().await
|
|
/// });
|
|
/// ```
|
|
pub fn execute<R, F>(future: F) -> R
|
|
where F: std::future::Future<Output = R> + Send
|
|
{
|
|
async_main(future)
|
|
}
|
|
|
|
/// Returns a future that evaluates to `true` exactly when there is a presently
|
|
/// running tokio async runtime that was likely started by Rocket.
|
|
fn running_within_rocket_async_rt() -> impl std::future::Future<Output = bool> {
|
|
use futures::FutureExt;
|
|
|
|
tokio::task::spawn_blocking(|| {
|
|
let this = std::thread::current();
|
|
this.name().map_or(false, |s| s.starts_with(WORKER_PREFIX))
|
|
}).map(|r| r.unwrap_or(false))
|
|
}
|