mirror of https://github.com/rwf2/Rocket.git
270 lines
11 KiB
Markdown
270 lines
11 KiB
Markdown
|
# Rocket 0.3: Fairings, TLS, Private Cookies
|
||
|
|
||
|
<p class="metadata"><strong>
|
||
|
Posted by <a href="https://sergio.bz">Sergio Benitez</a> on July 14, 2017
|
||
|
</strong></p>
|
||
|
|
||
|
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 was developed over the course of 6
|
||
|
months. 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, expressibility,
|
||
|
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) or learning more from [the
|
||
|
overview](/overview).
|
||
|
|
||
|
## What's New?
|
||
|
|
||
|
Rocket 0.3 is _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/SergiioBenitez/Rocket/blob/v0.3/CHANGELOG.md
|
||
|
|
||
|
### 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`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html
|
||
|
[fairings guide]: /guide/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/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<String> {
|
||
|
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<Redirect> {
|
||
|
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`]: https://api.rocket.rs/rocket/http/enum.Cookies.html
|
||
|
[`get_private`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.get_private
|
||
|
[`add_private`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.add_private
|
||
|
[`remove_private`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.remove_private
|
||
|
[private cookies]: /guide/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/requests/#field-renaming) section of the guide.
|
||
|
|
||
|
[`FromForm`]: https://api.rocket.rs/rocket/request/trait.FromForm.html
|
||
|
|
||
|
### And Plenty More!
|
||
|
|
||
|
In addition to the four highlighted above, Rocket 0.3 also ships with 26 other
|
||
|
new features! Be sure to check out the [CHANGELOG] for the complete list.
|
||
|
|
||
|
## Breaking Changes
|
||
|
|
||
|
This release includes many breaking changes. To keep this release note short,
|
||
|
please see the
|
||
|
[CHANGELOG](https://github.com/SergiioBenitez/Rocket/blob/v0.3/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 capatilized 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<u8>` 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`]: https://api.rocket.rs/rocket/struct.Request.html
|
||
|
[`State`]: https://api.rocket.rs/rocket/struct.State.html
|
||
|
[`Config`]: https://api.rocket.rs/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/SergioBenitez/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/SergioBenitez/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/SergioBenitez/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/state/#databases
|
||
|
|
||
|
## Contributors to v0.3
|
||
|
|
||
|
The following wonderful people helped make Rocket v0.3 happen:
|
||
|
|
||
|
<ul class="columns">
|
||
|
<li>Alan Stoate</li>
|
||
|
<li>Alexey Zabelin</li>
|
||
|
<li>Anton Pirker</li>
|
||
|
<li>Fabrice Desré</li>
|
||
|
<li>Ivar Abrahamsen</li>
|
||
|
<li>Josh Holmer</li>
|
||
|
<li>Joshua Rombauer</li>
|
||
|
<li>Lance Carlson</li>
|
||
|
<li>Lori Holden</li>
|
||
|
<li>Roman Frołow</li>
|
||
|
<li>Ryan Leckey</li>
|
||
|
<li>Stephan Buys</li>
|
||
|
<li>Tomek Wałkuski</li>
|
||
|
<li>Vesa Kaihlavirta</li>
|
||
|
<li>Yong Wen Chua</li>
|
||
|
</ul>
|
||
|
|
||
|
Thank you all! Your contributions are greatly appreciated!
|
||
|
|
||
|
Looking to help with Rocket's development? Head over to [Rocket's
|
||
|
GitHub](https://github.com/SergioBenitez/Rocket#contributing) and start
|
||
|
contributing!
|