diff --git a/CHANGELOG.md b/CHANGELOG.md index 207bb88b..fb56155b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,557 @@ +# Version 0.5.0-rc.1 (Jun 09, 2021) + +## Major Features and Improvements + +This release introduces the following major features and improvements: + + * Support for [compilation on Rust's stable] release channel. + * A rewritten, fully asynchronous core with support for [`async`/`await`]. + * [Feature-complete forms support] including multipart, collections, [ad-hoc validation], and + [context](https://rocket.rs/v0.5-rc/guide/requests/#context). + * [Sentinels]: automatic verification of application state at start-up to prevent runtime errors. + * [Graceful shutdown] with configurable signaling, grace periods, notification via [`Shutdown`]. + * An entirely new, flexible and robust [configuration system] based on [Figment]. + * Typed [asynchronous streams] and [Server-Sent Events] with generator syntax. + * Graduation of `json`, `msgpack`, and `uuid` `rocket_contrib` [features into core]. + * An automatically enabled [`Shield`]: security and privacy headers for all responses. + * Type-system enforced [incoming data limits] to mitigate memory-based DoS attacks. + * Compile-time URI literals via a fully revamped [`uri!`] macro. + * Full support for [UTF-8 characters] in routes and catchers. + * Precise detection of unmanaged state and missing database, template fairings with [sentinels]. + * Typed [build phases] with strict application-level guarantees. + * [Ignorable segments]: wildcard route matching with no typing restrictions. + * First-class [support for `serde`] for built-in guards and types. + * New application launch attributes: + [`#[launch]`](https://api.rocket.rs/v0.5-rc/rocket/attr.launch.html) and + [`#[rocket::main]`](https://api.rocket.rs/v0.5-rc/rocket/attr.main.html). + * [Default catchers] via `#[catch(default)]`, which handle _any_ status code. + * [Catcher scoping] to narrow the scope of a catcher to a URI prefix. + * Built-in libraries and support for [asynchronous testing]. + * A [`TempFile`] data and form guard for automatic uploading to a temporary file. + * A [`Capped`] data and form guard which enables detecting truncation due to data limits. + * Support for dynamic and static prefixing and suffixing of route URIs in [`uri!`]. + * Support for custom config profiles and [automatic typed config extraction]. + * Rewritten, zero-copy, RFC compliant URI parsers with support for URI-[`Reference`]s. + * Multi-segment parameters (``) which match _zero_ segments. + * A [`request::local_cache!`] macro for request-local storage of non-uniquely typed values. + * A [`CookieJar`] without "one-at-a-time" limitations. + * [Singleton fairings] with replacement and guaranteed uniqueness. + * [Data limit declaration in SI units]: "2 MiB", `2.mebibytes()`. + * Optimistic responding even when data is left unread or limits are exceeded. + * Fully decoded borrowed strings as dynamic parameters, form and data guards. + * Borrowed byte slices as data and form guards. + * Fail-fast behavior for [misconfigured secrets], file serving paths. + * Support for generics and custom generic bounds in + [`#[derive(Responder)]`](https://api.rocket.rs/v0.5-rc/rocket/derive.Responder.html). + * [Default ranking colors], which prevent more routing collisions automatically. + * Improved error logging with suggestions when common errors are detected. + * Completely rewritten examples including a new real-time [`chat`] application. + * Automatic support for HTTP/2 including `h2` ALPN. + +## Support for Rust Stable + +As a result of support for the stable release channel, the `#![feature(..)]` +crate attribute is no longer required for Rocket applications. The complete +canonical example with a single `hello` route becomes: + +```rust +#[macro_use] extern crate rocket; + +#[get("//")] +fn hello(name: &str, age: u8) -> String { + format!("Hello, {} year old named {}!", age, name) +} + +#[launch] +fn rocket() -> _ { + rocket::build().mount("/hello", routes![hello]) +} +``` + +
+ See a diff of the changes from v0.4. + +```diff +- #![feature(proc_macro_hygiene, decl_macro)] +- + #[macro_use] extern crate rocket; + + #[get("//")] +- fn hello(name: String, age: u8) -> String { ++ fn hello(name: &str, age: u8) -> String { + format!("Hello, {} year old named {}!", age, name) +} + +- fn main() { +- rocket::ignite().mount("/hello", routes![hello]).launch(); +- } ++ #[launch] ++ fn rocket() -> _ { ++ rocket::build().mount("/hello", routes![hello]) ++ } +``` + +
+ +## Breaking Changes + +This release includes many breaking changes. The most significant changes are listed below. + +### Silent Changes + +These changes are invisible to the compiler and will _not_ yield errors or warnings at compile-time. +We **strongly** advise all application authors to review this list carefully. + + * Blocking I/O (long running compute, synchronous `sleep()`, `Mutex`, `RwLock`, etc.) may prevent + the server from making progress and should be avoided, replaced with an `async` variant, or + performed in a worker thread. This is a consequence of Rust's cooperative `async` multitasking. + For details, see the new [multitasking] section of the guide. + * `ROCKET_ENV` is now `ROCKET_PROFILE`. A warning is emitted a launch time if the former is set. + * The default profile for debug builds is now `debug`, not `dev`. + * The default profile for release builds is now `release`, not `prod`. + * `ROCKET_LOG` is now `ROCKET_LOG_LEVEL`. A warning is emitted a launch time if the former is set. + * It is a launch-time error if `secrets` is enabled in non-`debug` profiles without a configured + `secret_key`. + * A misconfigured `template_dir` is reported as an error at launch time. + * [`FileServer::new()`] fails immediately if the provided directory does not exist. + * Catcher collisions result in a launch failure as opposed to a warning. + * Default ranks now range from `-12` to `-1`. There is no breaking change if only code generated + routes are used. Manually configured routes with negative ranks may collide or be considered in + a different order than before. + * The order of execution of path and query guards relative to each other is now unspecified. + * URIs beginning with `:` are properly recognized as invalid and rejected. + * URI normalization now normalizes the query part as well. + * The `Segments` iterator now returns percent-decoded `&str`s. + * Forms are now parsed leniently by the [`Form` guard]. Use [`Strict`] for the previous behavior. + * The `Option` form guard defaults to `None` instead of the default value for `T`. + * When data limits are exceeded, a `413 Payload Too Large` status is returned to the client. + * The default catcher now returns JSON when the client indicates preference via the `Accept` + header. + * Empty boolean form values parse as `true`: the query string `?f` is the same as `?f=true`. + * [`Created`] does not automatically send an `ETag` header if `R: Hash`. Use + [`Created::tagged_body`] instead. + * `FileServer` now forwards when a file is not found instead of failing with `404 Not Found`. + * [`Shield`] is enabled by default. You may need to disable or change policies if your application + depends on typically insecure browser features or if you wish to opt-in to different policies + than the defaults. + * [`CookieJar`] `get()`s do not return cookies added during request handling. See + [`CookieJar`#pending]. + +### General + + * [`Rocket`] is now generic over a [phase] marker: + * APIs operate on `Rocket`, `Rocket`, `Rocket`, or `Rocket` as + needed. + * The phase marker statically enforces state transitions in `Build`, `Ignite`, `Orbit` order. + * `rocket::ignite()` is now [`rocket::build()`], returns a `Rocket`. + * [`Rocket::ignite()`] transitions to the `Ignite` phase. This is run automatically on launch as + needed. + * Ignition finalizes configuration, runs `ignite` fairings, and verifies [sentinels]. + * [`Rocket::launch()`] transitions into the `Orbit` phase and starts the server. + * Methods like [`Request::rocket()`] that refer to a live Rocket instance return an + `&Rocket`. + * [Fairings] have been reorganized and restructured for `async`: + * Replaced `attach` fairings with `ignite` fairings. Unlike `attach` fairings, which ran + immediately at the time of attachment, `ignite` fairings are run when transitioning into the + `Ignite` phase. + * Replaced `launch` fairings with `liftoff` fairings. `liftoff` fairings are always run, even in + local clients, after the server begins listening and the concrete port is known. + * Introduced a new [configuration system] based on [Figment]: + * The concept of "environments" is replaced with "profiles". + * `ROCKET_ENV` is superseded by `ROCKET_PROFILE`. + * `ROCKET_LOG` is superseded by `ROCKET_LOG_LEVEL`. + * Profile names can now be arbitrarily chosen. The `dev`, `stage`, and `prod` profiles carry no + special meaning. + * The `debug` and `release` profiles are the default profiles for the debug and release + compilation profiles. + * A new specially recognized `default` profile specifies defaults for all profiles. + * The `global` profile has highest precedence, followed by the selected profile, followed by + `default`. + * Added support for limits specified in SI units: "1 MiB". + * Renamed `LoggingLevel` to [`LogLevel`]. + * Inlined error variants into the [`Error`] structure. + * Changed the type of `workers` to `usize` from `u16`. + * Changed accepted values for `keep_alive`: it is disabled with `0`, not `false` or `off`. + * Disabled the `secrets` feature (for private cookies) by default. + * Removed APIs related to "extras". Typed values can be extracted from the configured `Figment`. + * Removed `ConfigBuilder`: all fields of [`Config`] are public with constructors for each field + type. + * Many functions, traits, and trait bounds have been modified for `async`: + * [`FromRequest`], [`Fairing`], [`catcher::Handler`], [`route::Handler`], and [`FromData`] use + `#[async_trait]`. + * [`NamedFile::open`] is now an `async` function. + * Added [`Request::local_cache_async()`] for use in async request guards. + * Unsized `Response` bodies must be [`AsyncRead`] instead of `Read`. + * Automatically sized `Response` bodies must be [`AsyncSeek`] instead of `Seek`. + * The `local` module is split into two: [`rocket::local::asynchronous`] and + [`rocket::local::blocking`]. + * Functionality and features requiring Rust nightly were removed: + * Removed the `Try` implementation on [`Outcome`] which allowed using `?` with `Outcome`s. The + recommended replacement is the [`rocket::outcome::try_outcome!`] macro or the various + combinator functions on `Outcome`. + * [`Result` implements `Responder`] only when both `T` and `E` implement `Responder`. The + new [`Debug`] wrapping responder replaces `Result`. + * APIs which used the `!` type to now use [`std::convert::Infallible`]. + * [`Rocket::register()`] now takes a base path to scope catchers under as its first argument. + * `ErrorKind::Collision` has been renamed to [`ErrorKind::Collisions`]. + +[phase]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#phases + +### Routing and URIs + + * In `#[route(GET, path = "...")]`, `path` is now `uri`: `#[route(GET, uri = "...")]`. + * Multi-segment paths (`/`) now match _zero_ or more segments. + * A route URI like (`//`) now collides with (`/`), requires a `rank` to resolve. + * All catcher related types and traits moved to [`rocket::catcher`]. + * All route related types and traits moved to [`rocket::route`]. + * URI formatting types and traits moved to [`rocket::http::uri::fmt`]. + * `T` no longer converts to `Option` or `Result` for [`uri!`] query parameters. + * For optional query parameters, [`uri!`] requires using a wrapped value or `_`. + * `&RawStr` no longer implements `FromParam`: use `&str` instead. + * Percent-decoding is performed before calling `FromParam` implementations. + * `RawStr::url_decode()` and `RawStr::url_decode_lossy()` allocate as necessary, return `Cow`. + * `RawStr::from_str()` was replaced with `RawStr::new()`. + * `Origin::segments()` was replaced with `Origin.path().segments()`. + * `Origin::path()` and `Origin::query()` return `&RawStr` instead of `&str`. + * The type of `Route::name` is now `Option>`. + * `Route::set_uri` was replaced with [`Route::map_base()`]. + * `Route::uri()` returns a new [`RouteUri`] type. + * `Route::base` was removed in favor of `Route.uri().base()`. + +[`RouteUri`]: https://api.rocket.rs/v0.5-rc/rocket/route/struct.RouteUri.html + +### Data and Forms + + * Removed `FromDataSimple`. Use [`FromData`] and [`request::local_cache!`]. + * `Data` now has a lifetime: `Data<'r>`. + * [`Data::open()`] indelibly requires a data limit. + * All [`DataStream`] APIs require limits and return [`Capped`] types. + * Form types and traits were moved from `rocket::request` to [`rocket::form`]. + * Removed `FromQuery`. Dynamic query parameters (`#[get("/?")]`) use [`FromForm`] instead. + * Replaced `FromFormValue` with [`FromFormField`]. All `T: FromFormField` implement `FromForm`. + * Form field values are percent-decoded before calling [`FromFormField`] implementations. + * Renamed the `#[form(field = ...)]` attribute to `#[field(name = ...)]`. + +### Request Guards + + * Renamed `Cookies` to [`CookieJar`]. Its methods take `&self`. + * Renamed `Flash.name` to `Flash.kind`, `Flash.msg` to `Flash.message`. + * Replaced `Request::get_param()` with `Request::param()`. + * Replaced `Request::get_segments()` to `Request::segments()`. + * Replaced `Request::get_query_value()` with `Request::query_value()`. + * Replaced `Segments::into_path_buf()` with `Segments::to_path_buf()`. + * Replaced `Segments` and `QuerySegments` with [`Segments` and `Segments`]. + * [`Flash`] constructors to take `Into` instead of `AsRef`. + * The `State<'_, T>` request guard is now `&State`. + * Removed a lifetime from [`FromRequest`]: `FromRequest<'r>`. + * Removed a lifetime from [`FlashMessage`]: `FlashMessage<'_>`. + * Removed all `State` reexports except [`rocket::State`]. + +### Responders + + * Moved `NamedFile` to `rocket::fs::NamedFile` + * Replaced `Content` with `content::Custom`. + * `Response::body` and `Response::body_mut` are now infallible methods. + * Renamed `ResponseBuilder` to `Builder`. + * Removed direct `Response` body reading methods. Use methods on `r.body_mut()` instead. + * Removed inaccurate "chunked body" types and variants. + * Removed `Responder` `impl` for `Response`. Prefer custom responders with `#[derive(Responder)]`. + * Removed the unused reason phrase from `Status`. + +### Contrib Graduation + + * The `rocket_contrib` crate has been deprecated and should no longer be used. + * Several features previously in `rocket_contrib` were merged into `rocket` itself: + * `json`, `msgpack`, and `uuid` are now features of `rocket`. + * Moved `rocket_contrib::json` to [`rocket::serde::json`]. + * Moved `rocket_contrib::msgpack` to [`rocket::serde::msgpack`]. + * Moved `rocket_contrib::uuid` to [`rocket::serde::uuid`]. + * Moved `rocket_contrib::helmet` to [`rocket::shield`]. [`Shield`] is enabled by default. + * Moved `rocket_contrib::serve` to [`rocket::fs`], `StaticFiles` to [`rocket::fs::FileServer`]. + * Removed the now unnecessary `Uuid` and `JsonValue` wrapper types. + * Removed headers in `Shield` that are no longer respected by browsers. + * The remaining features from `rocket_contrib` are now provided by separate crates: + * Replaced `rocket_contrib::templates` with [`rocket_dyn_templates`]. + * Replaced `rocket_contrib::databases` with [`rocket_sync_db_pools`]. + * These crates are versioned and released independently of `rocket`. + * `rocket_contrib::databases::DbError` is now `rocket_sync_db_pools::Error`. + * Removed `redis`, `mongodb`, and `mysql` integrations which have upstream `async` drivers. + * The [`#[database]`](https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/attr.database.html) + attribute generates an [`async run()`] method instead of `Deref` implementations. + +## General Improvements + +In addition to new features and major improvements, Rocket saw the following improvements: + +### General + + * Added support for [raw identifiers] in the `FromForm` derive, `#[route]` macros, and `uri!`. + * Added support for uncased derived form fields: `#[field(name = uncased(...))]`. + * Added support for [default form field values]: `#[field(default = expr())]`. + * Added support for multiple `#[field]` attributes on struct fields. + * Added support for base16-encoded (a.k.a. hex-encoded) secret keys. + * Added [`Config::ident`] for configuring or removing the global `Server` header. + * Added [`Rocket::figment()`] and [`Rocket::catchers()`]. + * Added [`LocalRequest::json()`] and [`LocalResponse::json()`]. + * Added [`LocalRequest::msgpack()`] and [`LocalResponse::msgpack()`]. + * Added support for `use m::route; routes![route]` instead of needing `routes![m::route]`. + * Added support for [hierarchical data limits]: a limit of `a/b/c` falls back to `a/b` then `a`. + * Added [`LocalRequest::inner_mut()`]. `LocalRequest` implements `DerefMut` to `Request`. + * Added support for ECDSA and EdDSA TLS keys. + * Added associated constants in `Config` for all config parameter names. + * Added `ErrorKind::Config` to represent errors in configuration at runtime. + * Added `rocket::fairing::Result` type alias, returned by `Fairing::on_ignite()`. + * All guard failures are logged at runtime. + * `Rocket::mount()` now accepts a base value of any type that implements `TryInto>`. + * The default error catcher's HTML has been compacted. + * The default error catcher returns JSON if requested by the client. + * Panics in routes or catchers are caught and forwarded to `500` error catcher. + * A detailed warning is emitted if a route or catcher panics. + * Emoji characters are no longer output on Windows. + * Fixed [`Error`] to not panic if a panic is already in progress. + * Introduced [`Reference`] and [`Asterisk`] URI types. + * Added support to [`UriDisplayQuery`] for C-like enums. + * The [`UriDisplayQuery`] derive now recognizes the `#[field]` attribute for field renaming. + * `Client` method builders accept `TryInto` allowing a `uri!()` to be used directly. + * [`Redirect`] now accepts a `TryFrom`, allowing fragment parts. + +### HTTP + + * Added support for HTTP/2. + * Added AVIF (`image/avif`) as a known media type. + * Added `EventStream` (`text/event-stream`) as a known media type. + * Added a `const` constructor for `MediaType`. + * Added aliases `Text`, `Bytes` for the `Plain`, `Binary` media types, respectively. + * Introduced [`RawStrBuf`], an owned `RawStr`. + * Added many new "pattern" methods to [`RawStr`]. + * Added [`RawStr::percent_encode()`] and [`RawStr::strip()`]. + * Added support for unencoded query characters in URIs that are frequently sent by browsers. + +### Request + + * Added support for all UTF-8 characters in route paths. + * Added support for percent-encoded `:` in socket or IP address values in [`FromFormValue`]. + * Added [`Request::rocket()`] to access the active `Rocket` instance. + * `Request::uri()` now returns an `&Origin<'r>` instead of `&Origin<'_>`. + * `Request::accept()`, `Request::content_type()` reflect changes to `Accept`, `Content-Type`. + * `Json`, `MsgPack` accept `T: Deserialize`, not only `T: DeserializeOwned`. + * Diesel SQLite connections in `rocket_sync_db_pools` use better defaults. + * The default number of workers for synchronous database pools is now `workers * 4`. + +### Response + + * Added [`Template::try_custom()`] for fallible template engine customization. + * Manually registered templates can now be rendered with `Template::render()`. + * Added support for the `X-DNS-Prefetch-Control` header to `Shield`. + * Added support for manually-set `expires` values for private cookies. + * Added support for type generics and custom generic bounds to + [`#[derive(Responder)]`](https://api.rocket.rs/v0.5-rc/rocket/derive.Responder.html). + * The `Server` header is only set if one isn't already set. + * Accurate `Content-Length` headers are sent even for partially read `Body`s. + +### Trait Implementations + + * Implemented `Clone` for `State`. + * Implemented `Copy` and `Clone` for `fairing::Info`. + * Implemented `Debug` for `Rocket` and `Client`. + * Implemented `Default` for `Status` (returns `Status::Ok`). + * Implemented `PartialEq`, `Eq`, `Hash`, `PartialOrd`, and `Ord` for `Status`. + * Implemented `Eq`, `Hash`, and `PartialEq<&str>` for `Origin`. + * Implemented `PartialEq>>` for `RawStr`. + * Implemented `std::error::Error` for `Error`. + * Implemented `Deref` and `DerefMut` for `LocalRequest` (to `Request`). + * Implemented `DerefMut` for `Form`, `LenientForm`. + * Implemented `From` for `Json`, `MsgPack`. + * Implemented `TryFrom` and `TryFrom<&str>` for `Origin`. + * Implemented `TryFrom` for each of the specific URI variants. + * Implemented `FromRequest` for `&Config`. + * Implemented `FromRequest` for `IpAddr`. + * Implemented `FromParam` for `PathBuf` + * Implemented `FromParam`, `FromData`, and `FromForm` for `&str`. + * Implemented `FromForm` for `Json`, `MsgPack`. + * Implemented `FromFormField` for `Cow` and `Capped>` + * Implemented `Responder` for `tokio::fs::File`. + * Implemented `Responder` for `(ContentType, R) where R: Responder`. + * Implemented `Responder` for `(Status, R) where R: Responder` which overrides `R`'s status. + * Implemented `Responder` for `std::io::Error` (behaves as `Debug`). + * Implemented `Responder` for `Either`, equivalently to `Result`. + * Implemented `Serialize` for `Flash`. + * Implemented `Serialize`, `Deserialize`, `UriDisplay` and `FromUriParam` for `uuid::Uuid` + * Implemented `Serialize`, `Deserialize` for `RawStr`. + * Implemented `Serialize`, `Deserialize` for all URI types. + +### Updated Dependencies + + * The `serde` dependency was introduced (`1.0`). + * The `futures` dependency was introduced (`0.3`). + * The `state` dependency was updated to `TODO: unreleased`. + * The `time` dependency was updated to `0.2`. + * The `binascii` dependency was introduced (`0.1`). + * The `ref-cast` dependency was introduced (`1.0`). + * The `atomic` dependency was introduced (`0.5`). + * The `parking_lot` dependency was introduced (`0.11`). + * The `ubtye` dependency was introduced (`0.10`). + * The `figment` dependency was introduced (`0.10`). + * The `rand` dependency was introduced (`0.8`). + * The `either` dependency was introduced (`1.0`). + * The `pin-project-lite` dependency was introduced (`0.2`). + * The `indexmap` dependency was introduced (`1.0`). + * The `tempfile` dependency was introduced (`3.0`). + * The `async-trait` dependency was introduced (`0.1`). + * The `async-stream` dependency was introduced (`0.3`). + * The `multer` dependency was introduced (`2.0`). + * The `tokio` dependency was introduced (`1.6.1`). + * The `tokio-util` dependency was introduced (`0.6`). + * The `tokio-stream` dependency was introduced (`0.1.6`). + * The `bytes` dependency was introduced (`1.0`). + * The `rmp-serde` dependency was updated to `0.15`. + * The `uuid` dependency was updated to `0.8`. + * The `tera` dependency was updated to `1.10`. + * The `handlebars` dependency was updated to `3.0`. + * The `normpath` dependency was introduced (`0.3`). + * The `postgres` dependency was updated to `0.19`. + * The `rusqlite` dependency was updated to `0.25`. + * The `r2d2_sqlite` dependency was updated to `0.18`. + * The `memcache` dependency was updated to `0.15`. + +## Infrastructure + + * Rocket now uses the 2018 edition of Rust. + * Added visible `use` statements to examples in the guide. + * Split examples into a separate workspace from the non-example crates. + * Updated documentation for all changes. + * Fixed many typos, errors, and broken links throughout documentation and examples. + * Improved the general robustness of macros, and the quality and frequency of error messages. + * Benchmarks now use `criterion` and datasets extracted from real-world projects. + * Fixed the SPDX license expressions in `Cargo.toml` files. + * Added support to `test.sh` for a `+` flag (e.g. `+stable`) to pass to `cargo`. + * Added support to `test.sh` for extra flags to be passed on to `cargo`. + * Migrated CI to Github Actions. + +[`async`/`await`]: https://rocket.rs/v0.5-rc/guide/overview/#async-routes +[compilation on Rust's stable]: https://rocket.rs/v0.5-rc/guide/getting-started/#installing-rust +[Feature-complete forms support]: https://rocket.rs/v0.5-rc/guide/requests/#forms +[configuration system]: https://rocket.rs/v0.5-rc/guide/configuration/#configuration +[graceful shutdown]: https://api.rocket.rs/v0.5-rc/rocket/config/struct.Shutdown.html#summary +[asynchronous testing]: https://rocket.rs/v0.5-rc/guide/testing/#asynchronous-testing +[UTF-8 characters]: https://rocket.rs/v0.5-rc/guide/requests/#static-parameters +[ignorable segments]: https://rocket.rs/v0.5-rc/guide/requests/#ignored-segments +[Catcher scoping]: https://rocket.rs/v0.5-rc/guide/requests/#scoping +[ad-hoc validation]: https://rocket.rs/v0.5-rc/guide/requests#ad-hoc-validation +[incoming data limits]: https://rocket.rs/v0.5-rc/guide/requests/#streaming +[build phases]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#phases +[Singleton fairings]: https://api.rocket.rs/v0.5-rc/rocket/fairing/trait.Fairing.html#singletons +[features into core]: https://api.rocket.rs/v0.5-rc/rocket/index.html#features +[Data limit declaration in SI units]: https://api.rocket.rs/v0.5-rc/rocket/data/struct.ByteUnit.html +[support for `serde`]: https://api.rocket.rs/v0.5-rc/rocket/serde/index.html +[automatic typed config extraction]: https://api.rocket.rs/v0.5-rc/rocket/fairing/struct.AdHoc.html#method.config +[misconfigured secrets]: https://api.rocket.rs/v0.5-rc/rocket/config/struct.SecretKey.html +[default ranking colors]: https://rocket.rs/v0.5-rc/guide/requests/#default-ranking +[`chat`]: https://github.com/SergioBenitez/Rocket/tree/v0.5-rc/examples/chat +[`Form` guard]: https://api.rocket.rs/v0.5-rc/rocket/form/struct.Form.html +[`Strict`]: https://api.rocket.rs/v0.5-rc/rocket/form/struct.Strict.html +[`CookieJar`#pending]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.CookieJar.html#pending +[`rocket::serde::json`]: https://api.rocket.rs/v0.5-rc/rocket/serde/json/index.html +[`rocket::serde::msgpack`]: https://api.rocket.rs/v0.5-rc/rocket/serde/msgpack/index.html +[`rocket::serde::uuid`]: https://api.rocket.rs/v0.5-rc/rocket/serde/uuid/index.html +[`rocket::shield`]: https://api.rocket.rs/v0.5-rc/rocket/shield/index.html +[`rocket::fs`]: https://api.rocket.rs/v0.5-rc/rocket/fs/index.html +[`async run()`]: https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/index.html#handlers +[`LocalRequest::json()`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/struct.LocalRequest.html#method.json +[`LocalRequest::msgpack()`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/struct.LocalRequest.html#method.msgpack +[`LocalResponse::json()`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/struct.LocalResponse.html#method.json +[`LocalResponse::msgpack()`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/struct.LocalResponse.html#method.msgpack +[hierarchical data limits]: https://api.rocket.rs/v0.5-rc/rocket/data/struct.Limits.html#hierarchy +[default form field values]: https://rocket.rs/v0.5-rc/guide/requests/#defaults +[`Config::ident`]: https://api.rocket.rs/rocket/struct.Config.html#structfield.ident +[`tokio`]: https://tokio.rs/ +[Figment]: https://docs.rs/figment/0.10/figment/ +[`TempFile`]: https://api.rocket.rs/v0.5-rc/rocket/fs/enum.TempFile.html +[`Contextual`]: https://rocket.rs/v0.5-rc/guide/requests/#context +[`Capped`]: https://api.rocket.rs/v0.5-rc/rocket/data/struct.Capped.html +[default catchers]: https://rocket.rs/v0.5-rc/guide/requests/#default-catchers +[URI types]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/index.html +[`uri!`]: https://api.rocket.rs/v0.5-rc/rocket/macro.uri.html +[`Reference`]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/struct.Reference.html +[`Asterisk`]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/struct.Asterisk.html +[`Redirect`]: https://api.rocket.rs/v0.5-rc/rocket/response/struct.Redirect.html +[`UriDisplayQuery`]: https://api.rocket.rs/v0.5-rc/rocket/derive.UriDisplayQuery.html +[`Shield`]: https://api.rocket.rs/v0.5-rc/rocket/shield/struct.Shield.html +[Sentinels]: https://api.rocket.rs/v0.5-rc/rocket/trait.Sentinel.html +[`request::local_cache!`]: https://api.rocket.rs/v0.5-rc/rocket/request/macro.local_cache.html +[`CookieJar`]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.CookieJar.html +[asynchronous streams]: https://rocket.rs/v0.5-rc/guide/responses/#async-streams +[Server-Sent Events]: https://api.rocket.rs/v0.5-rc/rocket/response/stream/struct.EventStream.html +[`fs::relative!`]: https://api.rocket.rs/v0.5-rc/rocket/fs/macro.relative.html +[`Shutdown`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Shutdown.html +[`Rocket`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html +[`rocket::build()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.build +[`Rocket::ignite()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.ignite +[`Rocket::launch()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.launch +[`Request::rocket()`]: https://api.rocket.rs/v0.5-rc/rocket/request/struct.Request.html#method.rocket +[Fairings]: https://rocket.rs/v0.5-rc/guide/fairings/ +[configuration system]: https://rocket.rs/v0.5-rc/guide/configuration/ +[`Poolable`]: https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/trait.Poolable.html +[`Config`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Config.html +[`Error`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Error.html +[`LogLevel`]: https://api.rocket.rs/v0.5-rc/rocket/config/enum.LogLevel.html +[`Rocket::register()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.register +[`NamedFile::open`]: https://api.rocket.rs/v0.5-rc/rocket/fs/struct.NamedFile.html#method.open +[`Request::local_cache_async()`]: https://api.rocket.rs/v0.5-rc/rocket/request/struct.Request.html#method.local_cache_async +[`FromRequest`]: https://api.rocket.rs/v0.5-rc/rocket/request/trait.FromRequest.html +[`Fairing`]: https://api.rocket.rs/v0.5-rc/rocket/fairing/trait.Fairing.html +[`catcher::Handler`]: https://api.rocket.rs/v0.5-rc/rocket/catcher/trait.Handler.html +[`route::Handler`]: https://api.rocket.rs/v0.5-rc/rocket/route/trait.Handler.html +[`FromData`]: https://api.rocket.rs/v0.5-rc/rocket/data/trait.FromData.html +[`AsyncRead`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html +[`AsyncSeek`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncSeek.html +[`rocket::local::asynchronous`]: https://api.rocket.rs/v0.5-rc/rocket/local/asynchronous/index.html +[`rocket::local::blocking`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/index.html +[`Outcome`]: https://api.rocket.rs/v0.5-rc/rocket/outcome/enum.Outcome.html +[`rocket::outcome::try_outcome!`]: https://api.rocket.rs/v0.5-rc/rocket/outcome/macro.try_outcome.html +[`Result` implements `Responder`]: https://api.rocket.rs/v0.5-rc/rocket/response/trait.Responder.html#provided-implementations +[`Debug`]: https://api.rocket.rs/v0.5-rc/rocket/response/struct.Debug.html +[`std::convert::Infallible`]: https://doc.rust-lang.org/stable/std/convert/enum.Infallible.html +[`ErrorKind::Collisions`]: https://api.rocket.rs/v0.5-rc/rocket/error/enum.ErrorKind.html#variant.Collisions +[`rocket::http::uri::fmt`]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/fmt/index.html +[`Data::open()`]: https://api.rocket.rs/v0.5-rc/rocket/data/struct.Data.html#method.open +[`DataStream`]: https://api.rocket.rs/v0.5-rc/rocket/data/struct.DataStream.html +[`rocket::form`]: https://api.rocket.rs/v0.5-rc/rocket/form/index.html +[`FromFormField`]: https://api.rocket.rs/v0.5-rc/rocket/form/trait.FromFormField.html +[`FromForm`]: https://api.rocket.rs/v0.5-rc/rocket/form/trait.FromForm.html +[`FlashMessage`]: https://api.rocket.rs/v0.5-rc/rocket/request/type.FlashMessage.html +[`Flash`]: https://api.rocket.rs/v0.5-rc/rocket/response/struct.Flash.html +[`rocket::State`]: https://api.rocket.rs/v0.5-rc/rocket/struct.State.html +[`Segments` and `Segments`]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/struct.Segments.html +[`Route::map_base()`]: https://api.rocket.rs/v0.5-rc/rocket/route/struct.Route.html#method.map_base +[`uuid` support]: https://api.rocket.rs/v0.5-rc/rocket/serde/uuid/index.html +[`json`]: https://api.rocket.rs/v0.5-rc/rocket/serde/json/index.html +[`msgpack`]: https://api.rocket.rs/v0.5-rc/rocket/serde/msgpack/index.html +[`rocket::serde::json::json!`]: https://api.rocket.rs/v0.5-rc/rocket/serde/json/macro.json.html +[`rocket::shield::Shield`]: https://api.rocket.rs/v0.5-rc/rocket/shield/struct.Shield.html +[`rocket::fs::FileServer`]: https://api.rocket.rs/v0.5-rc/rocket/fs/struct.FileServer.html +[`rocket_dyn_templates`]: https://api.rocket.rs/v0.5-rc/rocket_dyn_templates/index.html +[`rocket_sync_db_pools`]: https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/index.html +[multitasking]: https://rocket.rs/v0.5-rc/guide/overview/#multitasking +[`Created`]: https://api.rocket.rs/v0.5-rc/rocket/response/status/struct.Created.html +[`Created::tagged_body`]: https://api.rocket.rs/v0.5-rc/rocket/response/status/struct.Created.html#method.tagged_body +[raw identifiers]: https://doc.rust-lang.org/1.51.0/book/appendix-01-keywords.html#raw-identifiers +[`Rocket::config()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.config +[`Rocket::figment()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.figment +[`Rocket::state()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.state +[`Rocket::catchers()`]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.catchers +[`LocalRequest::inner_mut()`]: https://api.rocket.rs/v0.5-rc/rocket/local/blocking/struct.LocalRequest.html#method.inner_mut +[`RawStrBuf`]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.RawStrBuf.html +[`RawStr`]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.RawStr.html +[`RawStr::percent_encode()`]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.RawStr.html#method.percent_encode +[`RawStr::strip()`]: https://api.rocket.rs/v0.5-rc/rocket/http/struct.RawStr.html#method.strip_prefix +[`rocket::catcher`]: https://api.rocket.rs/v0.5-rc/rocket/catcher/index.html +[`rocket::route`]: https://api.rocket.rs/v0.5-rc/rocket/route/index.html +[`Segments::prefix_of()`]: https://api.rocket.rs/v0.5-rc/rocket/http/uri/struct.Segments.html#method.prefix_of +[`Template::try_custom()`]: https://api.rocket.rs/v0.5-rc/rocket_dyn_templates/struct.Template.html#method.try_custom +[`Template::custom`]: https://api.rocket.rs/v0.5-rc/rocket_dyn_templates/struct.Template.html#method.custom +[`FileServer::new()`]: https://api.rocket.rs/v0.5-rc/rocket/fs/struct.FileServer.html#method.new + # Version 0.4.10 (May 21, 2021) ## Core