Rocket/site/news/2023-05-26-version-0.5.md

326 lines
9.2 KiB
Markdown

# Rocket v0.5: Stable, Async, Sentinels, Figment, Shield, Streams, SSE, WebSockets, & More!
<p class="metadata"><strong>
Posted by <a href="https://sergio.bz">Sergio Benitez</a> on May 26, 2023
</strong></p>
Four years, almost a thousand commits, and over a thousand issues, discussions,
and PRs later, I am ~~relieved~~ thrilled to announce the general availability
of Rocket v0.5.
> **Rocket** is a backend web framework for Rust with a focus on usability,
> security, extensibility, and speed. Rocket makes it simple to write secure web
> applications without sacrificing usability or performance.
We encourage all users to upgrade. For a guided upgrade from Rocket v0.4 to
Rocket v0.5, please consult the newly available [upgrading guide]. Rocket v0.4
will continue to be supported and receive security updates until the next major
release.
[upgrading guide]: ../../guide/upgrading
## What's New?
Almost every aspect has been reevaluated with a focus on usability, security,
and consistency across the library and [broader ecosystem]. The changes are
numerous, so we focus on the most impactful changes here and encourage everyone
to read the [CHANGELOG] for a complete list. For answers to frequently asked
questions, see the new [FAQ].
[broader ecosystem]: ../../guide/faq/#releases
[CHANGELOG]: https://github.com/SergioBenitez/Rocket/blob/v0.5.0/CHANGELOG.md
[FAQ]: ../../guide/faq
### ⚓ Support for Stable `rustc`
Rocket v0.5 compiles and builds on Rust stable with an entirely asynchronous
core. This means that you can compile Rocket application with `rustc` from the
stable release channel.
Using the stable release channel ensures that _no_ breakages will occur when
upgrading your Rust compiler or Rocket. That being said, Rocket continues to
take advantage of features only present in the nightly channel.
### 📥 Async I/O
The new asynchronous core requires an async runtime to run. The new
[`launch`] and [`main`] attributes simplify starting a runtime suitable for
running Rocket applications. You should use [`launch`] whenever possible.
Additionally, the `rocket::ignite()` function has been renamed to
[`rocket::build()`]; calls to the function or method should be replaced
accordingly. Together, these two changes result in the following diff to what
was previously the `main` function:
```diff
- fn main() {
- rocket::ignite().mount("/hello", routes![hello]).launch();
- }
+ #[launch]
+ fn rocket() -> _ {
+ rocket::build().mount("/hello", routes![hello])
+ }
```
### 💂 Sentinels
Rocket v0.5 introduces [sentinels]. Entirely unique to Rocket, sentinels offer
an automatic last line of defense against runtime errors by enabling any type
that appears in a route to abort application launch if invalid conditions are
detected. For example, the [`&State<T>`] guard in v0.5 is a [`Sentinel`] that
aborts launch if the type `T` is not in managed state, thus preventing
associated runtime errors.
You should consider implementing `Sentinel` for your types if you have guards
(request, data, form, etc.) or responders that depend on `Rocket` state to
function properly. For example, consider a `MyResponder` that expects:
* An error catcher to be registered for the `400` status code.
* A specific type `T` to be in managed state.
Making `MyResponder` a sentinel that guards against these conditions is as
simple as:
```rust
use rocket::{Rocket, Ignite, Sentinel};
# struct MyResponder;
# struct T;
impl Sentinel for MyResponder {
fn abort(r: &Rocket<Ignite>) -> bool {
!r.catchers().any(|c| c.code == Some(400)) || r.state::<T>().is_none()
}
}
```
[sentinels]: @api/rocket/trait.Sentinel.html
[`Sentinel`]: @api/rocket/trait.Sentinel.html
[`&State<T>`]: @api/rocket/struct.State.html
### 🛡️ Shield
### 🌊 Streams and SSE
Rocket v0.5 introduces real-time, typed, `async` [streams]. The new [async
streams] section of the guide contains further details, and we encourage all
interested parties to see the new real-time, multi-room [chat example].
As a taste of what's possible, the following `stream` route emits a `"ping"`
Server-Sent Event every `n` seconds, defaulting to `1`:
```rust
# use rocket::*;
use rocket::response::stream::{Event, EventStream};;
use rocket::tokio::time::{interval, Duration};
#[get("/ping?<n>")]
fn stream(n: Option<u64>) -> EventStream![] {
EventStream! {
let mut timer = interval(Duration::from_secs(n.unwrap_or(1)));
loop {
yield Event::data("ping");
timer.tick().await;
}
}
}
```
[streams]: @api/rocket/response/stream/index.html
[async streams]: @guide/responses/#async-streams
[chat example]: @example/chat
### 🔌 WebSockets
Rocket v0.5 introduces support for HTTP connection upgrades via a new [upgrade
API]. The API allows responders to take over an HTTP connection and perform raw
I/O with the client. In other words, an HTTP connection can be _upgraded_ to any
protocol, including HTTP WebSockets!
The newly introduced [`rocket_ws`] library takes advantage of the new API to
implement first-class support for WebSockets entirely outside of Rocket's core.
The simplest use of the library, implementing an echo server and showcasing that
the incoming message stream is `async`, looks like this:
```rust
# use rocket::get;
# use rocket_ws as ws;
#[get("/echo")]
fn echo_compose(ws: ws::WebSocket) -> ws::Stream!['static] {
ws.stream(|io| io)
}
```
The simplified [async streams] generator syntax can also be used:
```rust
# use rocket::get;
# use rocket_ws as ws;
#[get("/echo")]
fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {
ws::Stream! { ws =>
for await message in ws {
yield message?;
}
}
}
```
For complete usage details, see the [`rocket_ws`] documentation.
[upgrade API]: @api/rocket/response/struct.Response.html#upgrading
[`rocket_ws`]: @api/rocket_ws
[GitHub issue tracker]: https://github.com/SergioBenitez/Rocket/issues
[GitHub discussions]: https://github.com/SergioBenitez/Rocket/discussions
[migration guide]: ../../guide/upgrading
[CHANGELOG]: https://github.com/SergioBenitez/Rocket/blob/v0.5-rc/CHANGELOG.md#version-050-rc2-may-9-2022
## Thank You
<ul class="columns">
<li>Aaron Leopold</li>
<li>Abdullah Alyan</li>
<li>Aditya</li>
<li>Alex Macleod</li>
<li>Alex Sears</li>
<li>Alexander van Ratingen</li>
<li>ami-GS</li>
<li>Antoine Martin</li>
<li>arctic-alpaca</li>
<li>arlecchino</li>
<li>Arthur Woimbée</li>
<li>atouchet</li>
<li>Aurora</li>
<li>badoken</li>
<li>Beep LIN</li>
<li>Ben Sully</li>
<li>Benedikt Weber</li>
<li>BlackDex</li>
<li>Bonex</li>
<li>Brenden Matthews</li>
<li>Brendon Federko</li>
<li>Brett Buford</li>
<li>Cedric Hutchings</li>
<li>Cezar Halmagean</li>
<li>Charles-Axel Dein</li>
<li>Compro Prasad</li>
<li>Daniel Wiesenberg</li>
<li>David Venhoek</li>
<li>Dimitri Sabadie</li>
<li>Dinu Blanovschi</li>
<li>Dominik Boehi</li>
<li>Doni Rubiagatra</li>
<li>Edgar Onghena</li>
<li>Edwin Svensson</li>
<li>est31</li>
<li>Felix Suominen</li>
<li>Filip Gospodinov</li>
<li>Flying-Toast</li>
<li>Follpvosten</li>
<li>Francois Stephany</li>
<li>Gabriel Fontes</li>
<li>gcarq</li>
<li>George Cheng</li>
<li>Giles Cope</li>
<li>Gonçalo Ribeiro</li>
<li>hiyoko3m</li>
<li>Howard Su</li>
<li>hpodhaisky</li>
<li>Ian Jackson</li>
<li>IFcoltransG</li>
<li>Indosaram</li>
<li>inyourface34456</li>
<li>J. Cohen</li>
<li>Jacob Pratt</li>
<li>Jacob Sharf</li>
<li>Jacob Simpson</li>
<li>Jakub Dąbek</li>
<li>Jakub Wieczorek</li>
<li>James Tai</li>
<li>Jason Hinch</li>
<li>Jeb Rosen</li>
<li>Jeremy Kaplan</li>
<li>Joakim Soderlund</li>
<li>Johannes Liebermann</li>
<li>John-John Tedro</li>
<li>Jonah Brüchert</li>
<li>Jonas Møller</li>
<li>Jonathan Dickinson</li>
<li>Jonty</li>
<li>Joscha</li>
<li>Joshua Nitschke</li>
<li>JR Heard</li>
<li>Juhasz Sandor</li>
<li>Julian Büttner</li>
<li>Juraj Fiala</li>
<li>Kenneth Allen</li>
<li>Kevin Wang</li>
<li>Kian-Meng Ang</li>
<li>Konrad Borowski</li>
<li>Leonora Tindall</li>
<li>lewis</li>
<li>Lionel G</li>
<li>Lucille Blumire</li>
<li>Mai-Lapyst</li>
<li>Manuel</li>
<li>Marc Schreiber</li>
<li>Marc-Stefan Cassola</li>
<li>Marshall Bowers</li>
<li>Martin1887</li>
<li>Martinez</li>
<li>Matthew Pomes</li>
<li>Maxime Guerreiro</li>
<li>meltinglava</li>
<li>Michael Howell</li>
<li>Mikail Bagishov</li>
<li>mixio</li>
<li>multisn8</li>
<li>Necmettin Karakaya</li>
<li>Ning Sun</li>
<li>Nya</li>
<li>Paolo Barbolini</li>
<li>Paul Smith</li>
<li>Paul van Tilburg</li>
<li>Paul Weaver</li>
<li>pennae</li>
<li>Petr Portnov</li>
<li>philipp</li>
<li>Pieter Frenssen</li>
<li>PROgrm_JARvis</li>
<li>Razican</li>
<li>Redrield</li>
<li>Rémi Lauzier</li>
<li>Riley Patterson</li>
<li>Rodolphe Bréard</li>
<li>Roger Mo</li>
<li>RotesWasser</li>
<li>rotoclone</li>
<li>Rudi Floren</li>
<li>Samuele Esposito</li>
<li>Scott McMurray</li>
<li>Sergio Benitez</li>
<li>Silas Sewell</li>
<li>Soham Roy</li>
<li>Stuart Hinson</li>
<li>Thibaud Martinez</li>
<li>Thomas Eckert</li>
<li>ThouCheese</li>
<li>Tilen Pintarič</li>
<li>timando</li>
<li>timokoesters</li>
<li>toshokan</li>
<li>TotalKrill</li>
<li>Vasili</li>
<li>Vladimir Ignatev</li>
<li>Wesley Norris</li>
<li>xelivous</li>
<li>YetAnotherMinion</li>
<li>Yohannes Kifle</li>
<li>Yusuke Kominami</li>
</ul>
## What's Next?