Rocket v0.5.0-rc.2 Release Notes

Release Date: 2022-05-09 // almost 2 years ago
  • Major Features and Improvements

    • Introduced [rocket_db_pools] for asynchronous database pooling.
    • Introduced support for [mutual TLS] and client [Certificate]s.
    • Added a [local_cache_once!] macro for request-local storage.
    • Added a [v0.4 to v0.5 migration guide] and [FAQ] to Rocket's website.
    • Introduced shutdown fairings.

    ๐Ÿ’ฅ Breaking Changes

    • Hash impls for MediaType and ContentType no longer consider media type parameters.
    • TLS config values are only available when the tls feature is enabled.
    • [MediaType::with_params()] and [ContentType::with_params()] are now builder methods.
    • Content-Type [content] responder type names are now prefixed with Raw.
    • The content::Plain responder is now called content::RawText.
    • The content::Custom<T> responder was removed in favor of (ContentType, T).
    • TLS config structs are now only available when the tls feature is enabled.
    • Removed CookieJar::get_private_pending() in favor of CookieJar::get_pending().
    • The [local_cache!] macro accepts fewer types. Use [local_cache_once!] as appropriate.
    • When requested, the FromForm implementations of Vec and Maps are now properly lenient.
    • To concord with browsers, the [ and ] characters are now accepted in URI paths.
    • The [ and ] characters are no longer encoded by [uri!].
    • Rocket::launch() allows Rocket recovery by returning the instance after shutdown.
    • ErrorKind::Runtime was removed; ErrorKind::Shutdown was added.

    General Improvements

    • [Rocket] is now #[must_use].
    • Support for HTTP/2 can be disabled by disabling the default http2 crate feature.
    • Added rocket::execute() for executing Rocket's launch() future.
    • Added the [context!] macro to [rocket_dyn_templates] for ad-hoc template contexts.
    • The time crate is re-exported from the crate root.
    • The FromForm, Responder, and UriDisplay derives now fully support generics.
    • Added helper functions to serde submodules.
    • The [Shield] HSTS preload header now includes includeSubdomains.
    • Logging ignores write! errors if stdout disappears, preventing panics.
    • Added Client::terminate() to run graceful shutdown in testing.
    • Shutdown now terminates the async runtime, never the process.

    HTTP

    • Introduced [Host] and the [&Host] request guard.
    • Added Markdown (text/markdown) as a known media type.
    • Added [RawStr::percent_encode_bytes()].
    • NODELAY is now enabled on all connections by default.
    • The TLS implementation handles handshakes off the main task, improving DoS resistance.

    Request

    • Added [Request::host()] to retrieve the client-requested host.

    Trait Implementations

    • Arc<T>, Box<T> where T: Responder now implement Responder.
    • [Method] implements Serialize and Deserialize.
    • [MediaType] and [ContentType] implement Eq.

    โšก๏ธ Updated Dependencies

    • The time dependency was updated to 0.3.
    • The handlebars dependency was updated to 4.0.
    • The memcache dependency was updated to 0.16.
    • The rustls dependency was updated to 0.20.

    Infrastructure

    • Rocket now uses the 2021 edition of Rust.

    โฌ†๏ธ [v0.4 to v0.5 migration guide]: https://rocket.rs/v0.5-rc/guide/upgrading-from-0.4/ ๐Ÿ™‹ [FAQ]: https://rocket.rs/v0.5-rc/guide/faq/


Previous changes from v0.5.0-rc.1

  • 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.
    • 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.
    • Automatic support for HTTP/2 including h2 ALPN.
    • 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] and #[rocket::main].
    • [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<T> 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-References.
    • Multi-segment parameters (<param..>) 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)].
    • [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.

    ๐Ÿ‘Œ Support for Rust Stable

    ๐Ÿ‘ As a result of support for Rust stable (Rust 2021 Edition and beyond), the #![feature(..)] crate attribute is no longer required for Rocket applications. The complete canonical example with a single hello route becomes:

    #[macro_use] extern crate rocket;
    
    #[get("/<name>/<age>")]
    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.

    - #![feature(proc_macro_hygiene, decl_macro)]
    -
     #[macro_use] extern crate rocket;
    
     #[get("/<name>/<age>")]
    - 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.
    • ROCKET_ADDRESS accepts only IP addresses, no longer resolves hostnames like localhost.
    • ROCKET_CLI_COLORS accepts booleans true, false in place of strings "on", "off".
    • 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 &strs.
    • Forms are now parsed leniently by the Form guard. Use Strict for the previous behavior.
    • The Option<T> 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<R> 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.

    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:
    • 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] and rocket_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] attribute generates an [async run()] method instead of Deref implementations.

    General

    • Rocket is now generic over a phase marker:
      • APIs operate on Rocket<Build>, Rocket<Ignite>, Rocket<Orbit>, or Rocket<P: Phase> as needed.
      • The phase marker statically enforces state transitions in Build, Ignite, Orbit order.
      • rocket::ignite() is now [rocket::build()], returns a Rocket<Build>.
      • 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<Orbit>.
    • 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:
    • Functionality and features requiring Rust nightly were removed:
    • Rocket::register() now takes a base path to scope catchers under as its first argument.
    • ErrorKind::Collision has been renamed to ErrorKind::Collisions.

    Routing and URIs

    • In #[route(GET, path = "...")], path is now uri: #[route(GET, uri = "...")].
    • Multi-segment paths (/<p..>) now match zero or more segments.
    • Codegen improvements preclude identically named routes and modules in the same namespace.
    • A route URI like (/<a>/<p..>) now collides with (/<a>), 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<T> or Result<T, _> 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<Cow<'static, str>>.
    • 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().

    Data and Forms

    • Data now has a lifetime: Data<'r>.
    • Data::open() indelibly requires a data limit.
    • Removed FromDataSimple. Use FromData and local_cache! or local_cache_once!.
    • All DataStream APIs require limits and return Capped<T> types.
    • Form types and traits were moved from rocket::request to rocket::form.
    • Removed FromQuery. Dynamic query parameters (#[get("/?<param>")]) 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<Path> and Segments<Query>.
    • Flash constructors to take Into<String> instead of AsRef<str>.
    • The State<'_, T> request guard is now &State<T>.
    • 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.

    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<Origin<'_>>.
    • 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<Origin> allowing a uri!() to be used directly.
    • Redirect now accepts a TryFrom<Reference>, allowing fragment parts.

    HTTP

    • Added support for HTTP/2, enabled by default via the http2 crate feature.
    • 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<T>, MsgPack<T> 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)].
    • The Server header is only set if one isn't already set.
    • Accurate Content-Length headers are sent even for partially read Bodys.

    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<Cow<'_, RawStr>>> for RawStr.
    • Implemented std::error::Error for Error.
    • Implemented Deref and DerefMut for LocalRequest (to Request).
    • Implemented DerefMut for Form, LenientForm.
    • Implemented From<T> for Json<T>, MsgPack<T>.
    • Implemented TryFrom<String> and TryFrom<&str> for Origin.
    • Implemented TryFrom<Uri> 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<T>, MsgPack<T>.
    • Implemented FromFormField for Cow and Capped<Cow>>
    • 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<std::io::Error>).
    • Implemented Responder for Either<T, E>, equivalently to Result<T, E>.
    • 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 0.5.
    • 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.

    ๐Ÿ‘ [Feature-complete forms support]: https://rocket.rs/v0.5-rc/guide/requests/#forms ๐Ÿ”ง [configuration system]: https://rocket.rs/v0.5-rc/guide/configuration/#configuration

    โœ… [asynchronous testing]: https://rocket.rs/v0.5-rc/guide/testing/#asynchronous-testing

    ๐Ÿ— [build phases]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#phases

    ๐Ÿ‘ [support for serde]: https://api.rocket.rs/v0.5-rc/rocket/serde/index.html

    0๏ธโƒฃ [default ranking colors]: https://rocket.rs/v0.5-rc/guide/requests/#default-ranking

    ๐Ÿ”€ [async run()]: https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/index.html#handlers

    0๏ธโƒฃ [default form field values]: https://rocket.rs/v0.5-rc/guide/requests/#defaults

    ๐Ÿ“„ [Figment]: https://docs.rs/figment/0.10/figment/

    0๏ธโƒฃ [default catchers]: https://rocket.rs/v0.5-rc/guide/requests/#default-catchers

    ๐Ÿ— [rocket::build()]: https://api.rocket.rs/v0.5-rc/rocket/struct.Rocket.html#method.build

    ๐Ÿ”ง [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

    ๐Ÿ“„ [AsyncRead]: https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html ๐Ÿ‘€ [AsyncSeek]: https://docs.rs/tokio/1/tokio/io/trait.AsyncSeek.html

    ๐Ÿ‘ [uuid support]: https://api.rocket.rs/v0.5-rc/rocket/serde/uuid/index.html

    ๐Ÿ”€ [rocket_sync_db_pools]: https://api.rocket.rs/v0.5-rc/rocket_sync_db_pools/index.html

    ๐Ÿ”ง [mutual TLS]: https://rocket.rs/v0.5-rc/guide/configuration/#mutual-tls