2022-06-10 18:21:15 +00:00
|
|
|
+++
|
|
|
|
summary = "an overview of Rocket's core concepts"
|
|
|
|
+++
|
|
|
|
|
2017-04-17 02:48:59 +00:00
|
|
|
# Overview
|
|
|
|
|
2018-10-22 21:47:35 +00:00
|
|
|
Rocket provides primitives to build web servers and applications with Rust:
|
|
|
|
Rocket provides routing, pre-processing of requests, and post-processing of
|
|
|
|
responses; the rest is up to you. Your application code instructs Rocket on what
|
|
|
|
to pre-process and post-process and fills the gaps between pre-processing and
|
|
|
|
post-processing.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
## Lifecycle
|
|
|
|
|
|
|
|
Rocket's main task is to listen for incoming web requests, dispatch the request
|
|
|
|
to the application code, and return a response to the client. We call the
|
2017-07-03 05:51:24 +00:00
|
|
|
process that goes from request to response the "lifecycle". We summarize the
|
|
|
|
lifecycle as the following sequence of steps:
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
1. **Routing**
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
Rocket parses an incoming HTTP request into native structures that your
|
|
|
|
code operates on indirectly. Rocket determines which request handler to
|
|
|
|
invoke by matching against route attributes declared in your application.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
2. **Validation**
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
Rocket validates the incoming request against types and guards present in
|
|
|
|
the matched route. If validation fails, Rocket _forwards_ the request to
|
|
|
|
the next matching route or calls an _error handler_.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
3. **Processing**
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
The request handler associated with the route is invoked with validated
|
|
|
|
arguments. This is the main business logic of an application. Processing
|
|
|
|
completes by returning a `Response`.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
4. **Response**
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
The returned `Response` is processed. Rocket generates the appropriate HTTP
|
|
|
|
response and sends it to the client. This completes the lifecycle. Rocket
|
|
|
|
continues listening for requests, restarting the lifecycle for each
|
|
|
|
incoming request.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
The remainder of this section details the _routing_ phase as well as additional
|
|
|
|
components needed for Rocket to begin dispatching requests to request handlers.
|
2017-07-10 11:59:55 +00:00
|
|
|
The sections following describe the request and response phases as well as other
|
|
|
|
components of Rocket.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
## Routing
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
Rocket applications are centered around routes and handlers. A _route_ is a
|
|
|
|
combination of:
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
* A set of parameters to match an incoming request against.
|
|
|
|
* A handler to process the request and return a response.
|
|
|
|
|
2017-07-03 05:51:24 +00:00
|
|
|
A _handler_ is simply a function that takes an arbitrary number of arguments and
|
|
|
|
returns any arbitrary type.
|
|
|
|
|
2017-04-17 02:48:59 +00:00
|
|
|
The parameters to match against include static paths, dynamic paths, path
|
|
|
|
segments, forms, query strings, request format specifiers, and body data. Rocket
|
|
|
|
uses attributes, which look like function decorators in other languages, to make
|
|
|
|
declaring routes easy. Routes are declared by annotating a function, the
|
|
|
|
handler, with the set of parameters to match against. A complete route
|
|
|
|
declaration looks like this:
|
|
|
|
|
|
|
|
```rust
|
2020-02-15 11:43:47 +00:00
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
|
2017-04-17 02:48:59 +00:00
|
|
|
#[get("/world")] // <- route attribute
|
|
|
|
fn world() -> &'static str { // <- request handler
|
2020-02-15 11:43:47 +00:00
|
|
|
"hello, world!"
|
2017-04-17 02:48:59 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This declares the `world` route to match against the static path `"/world"` on
|
2020-06-12 03:41:10 +00:00
|
|
|
incoming `GET` requests. Instead of `#[get]`, we could have used `#[post]` or
|
|
|
|
`#[put]` for other HTTP methods, or `#[catch]` for serving [custom error
|
|
|
|
pages](../requests/#error-catchers). Additionally, other route parameters may be
|
|
|
|
necessary when building more interesting applications. The
|
2022-06-10 18:21:15 +00:00
|
|
|
[Requests](../requests/) chapter, which follows this one, has further details on
|
2020-06-12 03:41:10 +00:00
|
|
|
routing and error handling.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
2020-07-22 19:44:13 +00:00
|
|
|
! note: We prefer `#[macro_use]`, but you may prefer explicit imports.
|
|
|
|
|
|
|
|
Throughout this guide and the majority of Rocket's documentation, we import
|
|
|
|
`rocket` explicitly with `#[macro_use]` even though the Rust 2018 edition
|
|
|
|
makes explicitly importing crates optional. However, explicitly importing with
|
|
|
|
`#[macro_use]` imports macros globally, allowing you to use Rocket's macros
|
|
|
|
anywhere in your application without importing them explicitly.
|
|
|
|
|
|
|
|
You may instead prefer to import macros explicitly or refer to them with
|
2021-04-08 02:01:48 +00:00
|
|
|
absolute paths: `use rocket::get;` or `#[rocket::get]`.
|
2020-07-22 19:44:13 +00:00
|
|
|
|
2017-04-17 02:48:59 +00:00
|
|
|
## Mounting
|
|
|
|
|
2018-10-22 21:47:35 +00:00
|
|
|
Before Rocket can dispatch requests to a route, the route needs to be _mounted_:
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
```rust
|
2020-02-15 11:43:47 +00:00
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
|
|
|
|
# #[get("/world")]
|
|
|
|
# fn world() -> &'static str {
|
|
|
|
# "hello, world!"
|
|
|
|
# }
|
|
|
|
|
2021-04-08 08:07:52 +00:00
|
|
|
rocket::build().mount("/hello", routes![world]);
|
2017-04-17 02:48:59 +00:00
|
|
|
```
|
|
|
|
|
2018-10-22 21:47:35 +00:00
|
|
|
The `mount` method takes as input:
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
1. A _base_ path to namespace a list of routes under, here, `/hello`.
|
2019-05-11 02:39:38 +00:00
|
|
|
2. A list of routes via the `routes!` macro: here, `routes![world]`, with
|
|
|
|
multiple routes: `routes![a, b, c]`.
|
2018-10-22 21:47:35 +00:00
|
|
|
|
2021-04-08 08:07:52 +00:00
|
|
|
This creates a new `Rocket` instance via the `build` function and mounts the
|
2020-11-03 20:50:31 +00:00
|
|
|
`world` route to the `/hello` base path, making Rocket aware of the route.
|
|
|
|
`GET` requests to `/hello/world` will be directed to the `world` function.
|
|
|
|
|
|
|
|
The `mount` method, like all other builder methods on `Rocket`, can be chained
|
|
|
|
any number of times, and routes can be reused by mount points:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
|
|
|
|
# #[get("/world")]
|
|
|
|
# fn world() -> &'static str {
|
|
|
|
# "hello, world!"
|
|
|
|
# }
|
|
|
|
|
2021-04-08 08:07:52 +00:00
|
|
|
rocket::build()
|
2020-11-03 20:50:31 +00:00
|
|
|
.mount("/hello", routes![world])
|
|
|
|
.mount("/hi", routes![world]);
|
|
|
|
```
|
|
|
|
|
|
|
|
By mounting `world` to both `/hello` and `/hi`, requests to `"/hello/world"`
|
|
|
|
_and_ `"/hi/world"` will be directed to the `world` function.
|
2018-10-22 21:47:35 +00:00
|
|
|
|
|
|
|
! note: In many cases, the base path will simply be `"/"`.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
## Launching
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
Rocket begins serving requests after being _launched_, which starts a
|
|
|
|
multi-threaded asynchronous server and dispatches requests to matching routes as
|
|
|
|
they arrive.
|
2017-04-17 02:48:59 +00:00
|
|
|
|
2021-06-10 19:31:46 +00:00
|
|
|
There are two mechanisms by which a `Rocket` can be launched. The first and
|
2020-11-03 20:50:31 +00:00
|
|
|
preferred approach is via the `#[launch]` route attribute, which generates a
|
|
|
|
`main` function that sets up an async runtime and starts the server. With
|
|
|
|
`#[launch]`, our complete _Hello, world!_ application looks like:
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
```rust
|
2018-10-05 04:44:42 +00:00
|
|
|
#[macro_use] extern crate rocket;
|
2017-04-17 02:48:59 +00:00
|
|
|
|
|
|
|
#[get("/world")]
|
|
|
|
fn world() -> &'static str {
|
|
|
|
"Hello, world!"
|
|
|
|
}
|
|
|
|
|
2020-07-22 23:10:02 +00:00
|
|
|
#[launch]
|
2021-04-14 01:12:39 +00:00
|
|
|
fn rocket() -> _ {
|
2021-04-08 08:07:52 +00:00
|
|
|
rocket::build().mount("/hello", routes![world])
|
2017-04-17 02:48:59 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Running the application, the console shows:
|
|
|
|
|
|
|
|
```sh
|
2020-11-03 20:50:31 +00:00
|
|
|
> cargo run
|
|
|
|
🔧 Configured for debug.
|
Introduce statically-enforced 'Rocket' phasing.
The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where
'Phase' is a newly introduced, sealed marker trait. The trait is
implemented by three new marker types representing the three launch
phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three
phases, in order, is enforced, as are the invariants guaranteed by each
phase. In particular, an instance of 'Rocket' is guaranteed to be in its
final configuration after the 'Build' phase and represent a running
local or public server in the 'Orbit' phase. The 'Ignite' phase serves
as an intermediate, enabling inspection of a finalized but stationary
instance. Transition between phases validates the invariants required
by the transition.
All APIs have been adjusted appropriately, requiring either an instance
of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or
'Rocket<Orbit>') or operating generically on a 'Rocket<P>'.
Documentation is also updated and substantially improved to mention
required and guaranteed invariants.
Additionally, this commit makes the following relevant changes:
* 'Rocket::ignite()' is now a public interface.
* 'Rocket::{build,custom}' methods can no longer panic.
* 'Launch' fairings are now 'ignite' fairings.
* 'Liftoff' fairings are always run, even in local mode.
* All 'ignite' fairings run concurrently at ignition.
* Launch logging occurs on launch, not any point prior.
* Launch log messages have improved formatting.
* A new launch error kind, 'Config', was added.
* A 'fairing::Result' type alias was introduced.
* 'Shutdown::shutdown()' is now 'Shutdown::notify()'.
Some internal changes were also introduced:
* Fairing 'Info' name for 'Templates' is now 'Templating'.
* Shutdown is implemented using 'tokio::sync::Notify'.
* 'Client::debug()' is used nearly universally in tests.
Resolves #1154.
Resolves #1136.
2021-04-14 02:26:45 +00:00
|
|
|
>> address: 127.0.0.1
|
|
|
|
>> port: 8000
|
|
|
|
>> workers: [..]
|
|
|
|
>> keep-alive: 5s
|
|
|
|
>> limits: [..]
|
|
|
|
>> tls: disabled
|
|
|
|
>> temp dir: /tmp
|
|
|
|
>> log level: normal
|
|
|
|
>> cli colors: true
|
|
|
|
🛰 Routes:
|
|
|
|
>> (world) GET /hello/world
|
2020-11-03 20:50:31 +00:00
|
|
|
🚀 Rocket has launched from http://127.0.0.1:8000
|
2017-04-17 02:48:59 +00:00
|
|
|
```
|
|
|
|
|
Introduce statically-enforced 'Rocket' phasing.
The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where
'Phase' is a newly introduced, sealed marker trait. The trait is
implemented by three new marker types representing the three launch
phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three
phases, in order, is enforced, as are the invariants guaranteed by each
phase. In particular, an instance of 'Rocket' is guaranteed to be in its
final configuration after the 'Build' phase and represent a running
local or public server in the 'Orbit' phase. The 'Ignite' phase serves
as an intermediate, enabling inspection of a finalized but stationary
instance. Transition between phases validates the invariants required
by the transition.
All APIs have been adjusted appropriately, requiring either an instance
of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or
'Rocket<Orbit>') or operating generically on a 'Rocket<P>'.
Documentation is also updated and substantially improved to mention
required and guaranteed invariants.
Additionally, this commit makes the following relevant changes:
* 'Rocket::ignite()' is now a public interface.
* 'Rocket::{build,custom}' methods can no longer panic.
* 'Launch' fairings are now 'ignite' fairings.
* 'Liftoff' fairings are always run, even in local mode.
* All 'ignite' fairings run concurrently at ignition.
* Launch logging occurs on launch, not any point prior.
* Launch log messages have improved formatting.
* A new launch error kind, 'Config', was added.
* A 'fairing::Result' type alias was introduced.
* 'Shutdown::shutdown()' is now 'Shutdown::notify()'.
Some internal changes were also introduced:
* Fairing 'Info' name for 'Templates' is now 'Templating'.
* Shutdown is implemented using 'tokio::sync::Notify'.
* 'Client::debug()' is used nearly universally in tests.
Resolves #1154.
Resolves #1136.
2021-04-14 02:26:45 +00:00
|
|
|
! tip: `#[launch]` infers the return type!
|
2020-11-03 20:50:31 +00:00
|
|
|
|
2021-04-14 01:12:39 +00:00
|
|
|
Special to Rocket's `#[launch]` attribute, the return type of a function
|
|
|
|
decorated with `#[launch]` is automatically inferred when the return type is
|
|
|
|
set to `_`. If you prefer, you can also set the return type explicitly to
|
|
|
|
`Rocket<Build>`.
|
2020-11-03 20:50:31 +00:00
|
|
|
|
|
|
|
If we visit `http://127.0.0.1:8000/hello/world`, we see `Hello, world!`, exactly
|
|
|
|
as we expected.
|
|
|
|
|
|
|
|
! note: This and other examples are on GitHub.
|
|
|
|
|
2021-04-08 02:01:48 +00:00
|
|
|
An expanded version of this example's complete crate, ready to `cargo run`,
|
2022-06-10 18:21:15 +00:00
|
|
|
can be found on [GitHub](@git/v0.5/examples/hello). You can find dozens of other
|
2021-04-08 02:01:48 +00:00
|
|
|
complete examples, spanning all of Rocket's features, in the [GitHub examples
|
2022-06-10 18:21:15 +00:00
|
|
|
directory](@git/v0.5/examples/).
|
2020-11-03 20:50:31 +00:00
|
|
|
|
2020-11-03 22:20:29 +00:00
|
|
|
The second approach uses the `#[rocket::main]` route attribute.
|
|
|
|
`#[rocket::main]` _also_ generates a `main` function that sets up an async
|
|
|
|
runtime but unlike `#[launch]`, allows _you_ to start the server:
|
2020-11-03 20:50:31 +00:00
|
|
|
|
2020-11-03 22:20:29 +00:00
|
|
|
```rust,no_run
|
2020-11-03 20:50:31 +00:00
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
#
|
|
|
|
# #[get("/world")]
|
|
|
|
# fn world() -> &'static str {
|
|
|
|
# "Hello, world!"
|
|
|
|
# }
|
|
|
|
|
2020-11-03 22:20:29 +00:00
|
|
|
#[rocket::main]
|
2021-06-30 17:19:36 +00:00
|
|
|
async fn main() -> Result<(), rocket::Error> {
|
2022-05-06 22:14:44 +00:00
|
|
|
let _rocket = rocket::build()
|
2020-11-03 20:50:31 +00:00
|
|
|
.mount("/hello", routes![world])
|
|
|
|
.launch()
|
2022-05-06 22:14:44 +00:00
|
|
|
.await?;
|
|
|
|
|
|
|
|
Ok(())
|
2020-11-03 20:50:31 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-11-03 22:20:29 +00:00
|
|
|
`#[rocket::main]` is useful when a handle to the `Future` returned by `launch()`
|
|
|
|
is desired, or when the return value of [`launch()`] is to be inspected. The
|
2021-04-08 02:01:48 +00:00
|
|
|
[error handling example] for instance, inspects the return value.
|
2020-11-03 20:50:31 +00:00
|
|
|
|
2022-06-10 18:21:15 +00:00
|
|
|
[`launch()`]: @api/v0.5/rocket/struct.Rocket.html#method.launch
|
|
|
|
[error handling example]: @git/v0.5/examples/error-handling
|
2020-01-16 00:12:44 +00:00
|
|
|
|
|
|
|
## Futures and Async
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
Rocket uses Rust [`Future`]s for concurrency. Asynchronous programming with
|
2020-01-16 00:12:44 +00:00
|
|
|
`Future`s and `async/await` allows route handlers to perform wait-heavy I/O such
|
2021-09-05 15:59:33 +00:00
|
|
|
as filesystem and network access while still allowing other requests to make
|
2020-11-03 20:50:31 +00:00
|
|
|
progress. For an overview of Rust `Future`s, see [Asynchronous Programming in
|
2020-01-16 00:12:44 +00:00
|
|
|
Rust](https://rust-lang.github.io/async-book/).
|
|
|
|
|
|
|
|
In general, you should prefer to use async-ready libraries instead of
|
|
|
|
synchronous equivalents inside Rocket applications.
|
|
|
|
|
|
|
|
`async` appears in several places in Rocket:
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
* [Routes] and [Error Catchers] can be `async fn`s. Inside an `async fn`, you
|
|
|
|
can `.await` `Future`s from Rocket or other libraries.
|
|
|
|
* Several of Rocket's traits, such as [`FromData`] and [`FromRequest`], have
|
|
|
|
methods that return `Future`s.
|
|
|
|
* [`Data`] and [`DataStream`], incoming request data, and `Response` and `Body`,
|
|
|
|
outgoing response data, are based on `tokio::io::AsyncRead` instead of
|
2020-01-16 00:12:44 +00:00
|
|
|
`std::io::Read`.
|
|
|
|
|
|
|
|
You can find async-ready libraries on [crates.io](https://crates.io) with the
|
|
|
|
`async` tag.
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
[`Future`]: @std/future/trait.Future.html
|
2022-06-10 18:21:15 +00:00
|
|
|
[`Data`]: @api/v0.5/rocket/struct.Data.html
|
|
|
|
[`DataStream`]: @api/v0.5/rocket/data/struct.DataStream.html
|
|
|
|
[Routes]: ../requests/
|
|
|
|
[Error Catchers]: ../requests/#error-catchers
|
|
|
|
[`FromData`]: ../requests/#body-data
|
|
|
|
[`FromRequest`]: ../requests/#request-guards
|
2020-11-03 20:50:31 +00:00
|
|
|
|
2020-01-16 00:12:44 +00:00
|
|
|
! note
|
|
|
|
|
2021-06-09 08:53:34 +00:00
|
|
|
Rocket v0.5 uses the tokio runtime. The runtime is started for you if you
|
2020-11-03 22:20:29 +00:00
|
|
|
use `#[launch]` or `#[rocket::main]`, but you can still `launch()` a Rocket
|
|
|
|
instance on a custom-built runtime by not using _either_ attribute.
|
2020-01-16 00:12:44 +00:00
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
### Async Routes
|
|
|
|
|
|
|
|
Rocket makes it easy to use `async/await` in routes.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
use rocket::tokio::time::{sleep, Duration};
|
2021-03-27 23:25:39 +00:00
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
#[get("/delay/<seconds>")]
|
|
|
|
async fn delay(seconds: u64) -> String {
|
|
|
|
sleep(Duration::from_secs(seconds)).await;
|
|
|
|
format!("Waited for {} seconds", seconds)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
First, notice that the route function is an `async fn`. This enables the use of
|
|
|
|
`await` inside the handler. `sleep` is an asynchronous function, so we must
|
|
|
|
`await` it.
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
### Multitasking
|
2020-01-16 00:12:44 +00:00
|
|
|
|
|
|
|
Rust's `Future`s are a form of *cooperative multitasking*. In general, `Future`s
|
2020-11-03 20:50:31 +00:00
|
|
|
and `async fn`s should only `.await` on operations and never block. Some common
|
|
|
|
examples of blocking include locking non-`async` mutexes, joining threads, or
|
|
|
|
using non-`async` library functions (including those in `std`) that perform I/O.
|
2020-01-16 00:12:44 +00:00
|
|
|
|
|
|
|
If a `Future` or `async fn` blocks the thread, inefficient resource usage,
|
|
|
|
stalls, or sometimes even deadlocks can occur.
|
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
Sometimes there is no good `async` alternative for a library or operation. If
|
|
|
|
necessary, you can convert a synchronous operation to an async one with
|
|
|
|
[`tokio::task::spawn_blocking`]:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
# #[macro_use] extern crate rocket;
|
|
|
|
use std::io;
|
2021-05-23 05:12:46 +00:00
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
use rocket::tokio::task::spawn_blocking;
|
|
|
|
|
|
|
|
#[get("/blocking_task")]
|
2021-05-23 05:12:46 +00:00
|
|
|
async fn blocking_task() -> io::Result<Vec<u8>> {
|
2021-05-22 23:21:19 +00:00
|
|
|
// In a real app, use rocket::fs::NamedFile or tokio::fs::File.
|
2020-11-03 20:50:31 +00:00
|
|
|
let vec = spawn_blocking(|| std::fs::read("data.txt")).await
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Interrupted, e))??;
|
|
|
|
|
|
|
|
Ok(vec)
|
|
|
|
}
|
|
|
|
```
|
2020-01-16 00:12:44 +00:00
|
|
|
|
2020-11-03 20:50:31 +00:00
|
|
|
[`tokio::task::spawn_blocking`]: @tokio/task/fn.spawn_blocking.html
|