# Rocket v0.3: Fairings, TLS, Private Cookies

Posted by Sergio Benitez on July 14, 2017

I'm excited to announce that the next major release of Rocket is available today! Rocket 0.3 is packed with new features and improvements that increase developer productivity, improve application security, and provide new opportunities for extensibility. Rocket 0.3 is the culmination of almost 6 months of work. During this time, more than 225 changes were committed, over 100 issues (primarily questions and feature requests) were closed, and over 40 pull requests were submitted. The Rocket community has proven steadfast in their support: a sincere thank you to everyone involved! ## About Rocket Rocket is a web framework for Rust with a focus on ease of use, expressiveness, and speed. Rocket makes it simple to write fast web applications without sacrificing flexibility or type safety. All with minimal code. Not already using Rocket? Join the thousands of users and dozens of companies happily using Rocket today! Rocket's extensive documentation makes it easy. Get started now by [reading through the guide](@guide-v0.3) or learning more from [the overview](../../overview). ## What's New? Rocket 0.3 is a _big_ release, packed with over 100 changes. We highlight the biggest new features here. For a complete description of everything new and different in 0.3, please see the [CHANGELOG]. [CHANGELOG]: https://github.com/rwf2/Rocket/blob/v0.3.0/CHANGELOG.md#version-030-jul-14-2017 ### Fairings Fairings bring structured middleware to Rocket. With fairings, Rocket applications can hook into the application lifecycle to record or rewrite information about incoming requests, outgoing responses, and the Rocket application itself. Rocket's fairings are a lot like middleware from other frameworks, but they bear a few key distinctions: * Fairings cannot directly terminate or respond to an incoming request. * Fairings cannot inject arbitrary, non-request data into a request. * Fairings _can_ prevent an application from launching. * Fairings _can_ inspect and modify the application's configuration. Fairings are implemented through Rocket's [`Fairing`] trait. The trait consists of callback methods that Rocket invokes as needed. A fairing can subscribe to receive callbacks for the following four events: * **Attach**: called when a fairing is first registered. * **Launch**: called immediately before the Rocket application launches. * **Request**: called just after a request is received. * **Response**: called when a response is ready to be returned. The new [fairings guide] describes fairings in detail, expands on their limitations and abilities, and includes implementation examples. I encourage you to experiment with fairings and report your experiences. As always, feedback is instrumental in solidifying a robust design. [`Fairing`]: @api-v0.3/rocket/fairing/trait.Fairing.html [fairings guide]: @guide-v0.3/fairings ### Native TLS Support Rocket 0.3 includes built-in, experimental support for TLS, powered by [`rustls`]. To enable TLS support, compile Rocket with the `tls` feature enabled. Then, configure file paths to an RSA certificate chain and corresponding private key in the `Rocket.toml` file or via environment variables: ```toml [global.tls] certs = "/path/to/certs.pem" key = "/path/to/key.pem" ``` TLS support in Rocket is experimental and not yet recommended for general use over the internet. Instead, prefer to place Rocket behind a mature reverse-proxy such as NGINX. That being said, use of Rocket's TLS support is encouraged for local networking (such as local-only IoT devices) or as required during development. For more details on Rocket's TLS support, see the [configuring TLS] section of the guide. [`rustls`]: https://github.com/ctz/rustls [configuring TLS]: @guide-v0.3/configuration/#configuring-tls ### Private Cookies In Rocket 0.3, cookies can be _private_. Private cookies are encrypted using authenticated encryption, a form of encryption which simultaneously provides confidentiality, integrity, and authenticity. This means that private cookies cannot be inspected, tampered with, or manufactured by clients. Retrieving, adding, and removing private cookies is done via the new [`get_private`], [`add_private`], and [`remove_private`] methods on the [`Cookies`] type. As an example, consider the code below which sets and retrieves a `user_id` private cookie in two routes: ```rust /// Retrieve the user's ID, if any. #[get("/user_id")] fn user_id(cookies: Cookies) -> Option { request.cookies() .get_private("user_id") .map(|cookie| format!("User ID: {}", cookie.value())) } /// Remove the `user_id` cookie. #[post("/logout")] fn logout(mut cookies: Cookies) -> Flash { cookies.remove_private(Cookie::named("user_id")); Flash::success(Redirect::to("/"), "Successfully logged out.") } ``` To encrypt private cookies, Rocket uses the 256-bit key specified in the `secret_key` configuration parameter. If one is not specified, Rocket automatically generates a fresh key at launch. For more details on private cookies, see the [private cookies] section of the guide. [`Cookies`]: @api-v0.3/rocket/http/enum.Cookies.html [`get_private`]: @api-v0.3/rocket/http/enum.Cookies.html#method.get_private [`add_private`]: @api-v0.3/rocket/http/enum.Cookies.html#method.add_private [`remove_private`]: @api-v0.3/rocket/http/enum.Cookies.html#method.remove_private [private cookies]: @guide-v0.3/requests/#private-cookies ### Form Field Naming In 0.2 and below, Rocket always matches form field names to structure field names exactly when deriving [`FromForm`]. This presented an issue when an invalid Rust identifier was used as a form field's name. For example, it was not possible to represent a form with a field name of "type" since `type` is a keyword and thus an illegal identifier. The following resulted in a compile-time error: ```rust #[derive(FromForm)] struct External { type: String } ``` In Rocket 0.3, you can ask Rocket to match against a different form field for a given structure field by using the `#[form(field = "name")]` field annotation. As a result, the "type" form field can now be captured using something like the following: ```rust #[derive(FromForm)] struct External { #[form(field = "type")] api_type: String } ``` Rocket will automatically match the form field named "type" to the structure field named `api_type`. For more details on form field naming, see the [field renaming](@guide-v0.3/requests/#field-renaming) section of the guide. [`FromForm`]: @api-v0.3/rocket/request/trait.FromForm.html ### And Plenty More! In addition to the four highlighted above, Rocket 0.3 also ships with the following new features: * A [`MsgPack`] type has been added for simple consumption and returning of MessagePack data. * [`Rocket::launch()`] returns launch failures ([`LaunchError`]) for inspection without panicking. * Routes without query parameters now match requests with or without query parameters. * [Default rankings] prefer static paths and routes with query string matches. * A native [`Accept`] header structure was added. * The [`Accept`] request header can be retrieved via [`Request::accept()`]. * All active routes can be retrieved via [`Rocket::routes()`]. * [`Response::body_string()`] was added to retrieve the response body as a `String`. * [`Response::body_bytes()`] was added to retrieve the response body as a `Vec`. * [`Response::content_type()`] was added to retrieve the Content-Type header of a response. * Data limits on incoming data are [now configurable](@guide-v0.3/configuration/#data-limits). * [`Request::limits()`] was added to retrieve incoming data limits. * Responders may dynamically adjust their response based on the incoming request. * [`Request::guard()`] was added for simple retrieval of request guards. * [`Request::route()`] was added to retrieve the active route, if any. * [`&Route`] is now a request guard. * The base mount path of a [`Route`] can be retrieved via `Route::base` or `Route::base()`. * `Config::{development, staging, production}` constructors were added for [`Config`]. * [`Config::get_datetime()`] was added to retrieve an extra as a `Datetime`. * Forms can be now parsed _leniently_ via the new [`LenientForm`] data guard. * The `?` operator can now be used with `Outcome`. * Quoted string, array, and table [configuration parameters] can be set via environment variables. * Log coloring is disabled when `stdout` is not a TTY. * [`FromForm`] is implemented for `Option`, `Result`. * The [`NotFound`] responder was added for simple **404** response construction. [`MsgPack`]: @api-v0.3/rocket_contrib/msgpack/struct.MsgPack.html [`Rocket::launch()`]: @api-v0.3/rocket/struct.Rocket.html#method.launch [`LaunchError`]: @api-v0.3/rocket/error/struct.LaunchError.html [Default rankings]: @api-v0.3/rocket/struct.Route.html [`&Route`]: @api-v0.3/rocket/struct.Route.html [`Route`]: @api-v0.3/rocket/struct.Route.html [`Accept`]: @api-v0.3/rocket/http/struct.Accept.html [`Request::accept()`]: @api-v0.3/rocket/struct.Request.html#method.accept [`contrib`]: @api-v0.3/rocket_contrib/ [`Rocket::routes()`]: @api-v0.3/rocket/struct.Rocket.html#method.routes [`Response::body_string()`]: @api-v0.3/rocket/struct.Response.html#method.body_string [`Response::body_bytes()`]: @api-v0.3/rocket/struct.Response.html#method.body_bytes [`Response::content_type()`]: @api-v0.3/rocket/struct.Response.html#method.content_type [`Request::guard()`]: @api-v0.3/rocket/struct.Request.html#method.guard [`Request::limits()`]: @api-v0.3/rocket/struct.Request.html#method.limits [`Request::route()`]: @api-v0.3/rocket/struct.Request.html#method.route [`Config`]: @api-v0.3/rocket/struct.Config.html [`Cookies`]: @api-v0.3/rocket/http/enum.Cookies.html [`Config::get_datetime()`]: @api-v0.3/rocket/struct.Config.html#method.get_datetime [`LenientForm`]: @api-v0.3/rocket/request/struct.LenientForm.html [configuration parameters]: @api-v0.3/rocket/config/index.html#environment-variables [`NotFound`]: @api-v0.3/rocket/response/status/struct.NotFound.html ## Breaking Changes This release includes many breaking changes such as support for `serde` 1.0. To keep this release note short, please see the [CHANGELOG](https://github.com/rwf2/Rocket/blob/v0.3.0/CHANGELOG.md#breaking-changes) for the full list of breaking changes along with a short note about how to handle the breaking change in existing applications. ## General Improvements In addition to new features, Rocket saw the following improvements: * "Rocket" is now capitalized in the `Server` HTTP header. * The generic parameter of `rocket_contrib::Json` defaults to `json::Value`. * The trailing '...' in the launch message was removed. * The launch message prints regardless of the config environment. * For debugging, `FromData` is implemented for `Vec` and `String`. * The port displayed on launch is the port resolved, not the one configured. * The `uuid` dependency was updated to `0.5`. * The `base64` dependency was updated to `0.6`. * The `toml` dependency was updated to `0.4`. * The `handlebars` dependency was updated to `0.27`. * The `tera` dependency was updated to `0.10`. * [`yansi`] is now used for all terminal coloring. * The `dev` `rustc` release channel is supported during builds. * [`Config`] is now exported from the root. * [`Request`] implements `Clone` and `Debug`. * The `workers` config parameter now defaults to `num_cpus * 2`. * Console logging for table-based config values is improved. * `PartialOrd`, `Ord`, and `Hash` are now implemented for [`State`]. * The format of a request is always logged when available. [`yansi`]: https://crates.io/crates/yansi [`Request`]: @api-v0.3/rocket/struct.Request.html [`State`]: @api-v0.3/rocket/struct.State.html [`Config`]: @api-v0.3/rocket/struct.Config.html ## What's Next? Rocket 0.4, of course! The focus of the next major release is two-fold: security and usability. The following major features are planned: 1. **Automatic CSRF protection across all payload-based requests ([#14](https://github.com/rwf2/Rocket/issues/14)).** This is a carry-over from the 0.3 wishlist. Rocket will automatically check the origin of requests made for HTTP `PUT`, `POST`, `DELETE`, and `PATCH` requests, allowing only valid requests to be dispatched. This includes checking form submissions and requests made via JavaScript. 2. **First-class database support ([#167](https://github.com/rwf2/Rocket/issues/167)).** Connecting a database to Rocket is presently [much wordier than necessary]. The plan for 0.4 is to minimize the amount of effort. At most, a couple of lines of configuration and a single line of initialization code should be required. 3. **Typed URL generation from routes ([#263](https://github.com/rwf2/Rocket/issues/263)).** Explicitly writing URLs is error-prone. Because routes are fully-typed in Rocket, it's possible to check that a URL corresponding to a route type-checks. In the next release, a `url!` macro will be available to automatically generate URLs for routes in a type-safe manner. [much wordier than necessary]: @guide-v0.3/state/#databases ## Contributors to v0.3 The following wonderful people helped make Rocket v0.3 happen:
  • Alan Stoate
  • Alexey Zabelin
  • Anton Pirker
  • Fabrice Desré
  • Ivar Abrahamsen
  • Josh Holmer
  • Joshua Rombauer
  • Lance Carlson
  • Lori Holden
  • Roman Frołow
  • Ryan Leckey
  • Stephan Buys
  • Tomek Wałkuski
  • Vesa Kaihlavirta
  • Yong Wen Chua
Thank you all! Your contributions are greatly appreciated! Looking to help with Rocket's development? Head over to [Rocket's GitHub](https://github.com/rwf2/Rocket#contributing) and start contributing!