Reorganize and upgrade markup in site docs.

The guide is now in docs/guide. All other site assets are being migrated
to a separate repository. The guide markup has been upgraded to take
advantages of improvements in the static site generator used to build
the Rocket website.
This commit is contained in:
Sergio Benitez 2024-03-02 00:04:24 -08:00
parent 5ee9fbd20b
commit c99ed8b7c6
21 changed files with 119 additions and 1384 deletions

View File

@ -149,4 +149,4 @@ Rocket is licensed under either of the following, at your option:
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
The Rocket website source is licensed under [separate terms](site/README.md#license).
The Rocket website docs are licensed under [separate terms](docs/LICENSE).

View File

@ -619,56 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@ -2,7 +2,7 @@
Rocket is a web framework for Rust. If you'd like, you can think of Rocket as
being a more flexible, friendly medley of [Rails](http://rubyonrails.org),
[Flask](http://flask.pocoo.org/),
[Flask](https://flask.palletsprojects.com/),
[Bottle](http://bottlepy.org/docs/dev/index.html), and
[Yesod](http://www.yesodweb.com/). We prefer to think of Rocket as something
new. Rocket aims to be fast, easy, and flexible. It also aims to be _fun_, and

View File

@ -3,7 +3,7 @@
Before you can start writing a Rocket application, you'll need a **nightly**
version of Rust installed. We recommend you use [rustup](https://rustup.rs/) to
install or configure such a version. If you don't have Rust installed and would
like extra guidance doing so, see the [getting started](/guide/getting-started)
like extra guidance doing so, see the [getting started](../getting-started/)
section.
## Running Examples
@ -15,7 +15,7 @@ For instance, the following set of commands runs the `hello_world` example:
```sh
git clone https://github.com/SergioBenitez/Rocket
cd Rocket
git checkout v0.3.17
git checkout v0.3
cd examples/hello_world
cargo run
```

View File

@ -71,7 +71,7 @@ fn world() -> &'static str { // <- request handler
This declares the `world` route to match against the static path `"/world"` on
incoming `GET` requests. The `world` route is simple, but additional route
parameters are necessary when building more interesting applications. The
[Requests](/guide/requests) section describes the available options for
[Requests](../requests/) section describes the available options for
constructing routes.
## Mounting
@ -179,7 +179,7 @@ we expected.
A version of this example's complete crate, ready to `cargo run`, can be found
on
[GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/hello_world).
[GitHub](@git/v0.3/examples/hello_world).
You can find dozens of other complete examples, spanning all of Rocket's
features, in the [GitHub examples
directory](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/).
directory](@git/v0.3/examples/).

View File

@ -38,7 +38,7 @@ to the root path:
```
The grammar for these attributes is defined formally in the
[`rocket_codegen`](https://api.rocket.rs/rocket_codegen/) API docs.
[`rocket_codegen`](@api/v0.3/rocket_codegen/) API docs.
### HEAD Requests
@ -56,7 +56,7 @@ request methods under certain conditions. If a `POST` request contains a body of
field has the name `_method` and a valid HTTP method name as its value (such as
`"PUT"`), that field's value is used as the method for the incoming request.
This allows Rocket applications to submit non-`POST` forms. The [todo
example](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/todo/static/index.html.tera#L47)
example](@git/v0.3/examples/todo/static/index.html.tera#L47)
makes use of this feature to submit `PUT` and `DELETE` requests from a web form.
## Dynamic Segments
@ -95,8 +95,8 @@ fn hello(name: String, age: u8, cool: bool) -> String {
}
```
[`FromParam`]: https://api.rocket.rs/rocket/request/trait.FromParam.html
[`FromParam` API docs]: https://api.rocket.rs/rocket/request/trait.FromParam.html
[`FromParam`]: @api/v0.3/rocket/request/trait.FromParam.html
[`FromParam` API docs]: @api/v0.3/rocket/request/trait.FromParam.html
### Raw Strings
@ -114,7 +114,7 @@ segment, a `RawStr` points to a potentially undecoded string. By contrast, a
you want direct but potentially unsafe access to the string (`&RawStr`), or safe
access to the string at the cost of an allocation (`String`).
[`RawStr`]: https://api.rocket.rs/rocket/http/struct.RawStr.html
[`RawStr`]: @api/v0.3/rocket/http/struct.RawStr.html
## Forwarding
@ -215,7 +215,7 @@ fn files(file: PathBuf) -> Option<NamedFile> {
}
```
[`FromSegments`]: https://api.rocket.rs/rocket/request/trait.FromSegments.html
[`FromSegments`]: @api/v0.3/rocket/request/trait.FromSegments.html
## Format
@ -287,8 +287,8 @@ short-circuiting; if one guard fails, the remaining are not attempted. To learn
more about request guards and implementing them, see the [`FromRequest`]
documentation.
[`FromRequest`]: https://api.rocket.rs/rocket/request/trait.FromRequest.html
[`Cookies`]: https://api.rocket.rs/rocket/http/enum.Cookies.html
[`FromRequest`]: @api/v0.3/rocket/request/trait.FromRequest.html
[`Cookies`]: @api/v0.3/rocket/http/enum.Cookies.html
### Custom Guards
@ -380,7 +380,7 @@ be set and removed using the `Cookies` guard. The [cookies example] on GitHub
illustrates further use of the `Cookies` type to get and set cookies, while the
[`Cookies`] documentation contains complete usage information.
[cookies example]: https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/cookies
[cookies example]: @git/v0.3/examples/cookies
### Private Cookies
@ -414,7 +414,7 @@ fn logout(mut cookies: Cookies) -> Flash<Redirect> {
}
```
[`Cookies::add()`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.add
[`Cookies::add()`]: @api/v0.3/rocket/http/enum.Cookies.html#method.add
### Secret Key
@ -432,11 +432,11 @@ usually done through tools like `openssl`. Using `openssl`, a 256-bit base64 key
can be generated with the command `openssl rand -base64 32`.
For more information on configuration, see the
[Configuration](/guide/configuration) section of the guide.
[Configuration](../configuration/) section of the guide.
[`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
[`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
### One-At-A-Time
@ -489,7 +489,7 @@ fn new(input: T) -> String { ... }
Any type that implements [`FromData`] is also known as _data guard_.
[`FromData`]: https://api.rocket.rs/rocket/data/trait.FromData.html
[`FromData`]: @api/v0.3/rocket/data/trait.FromData.html
### Forms
@ -525,8 +525,8 @@ forward or failure can be caught by using the `Option` and `Result` types:
fn new(task: Option<Form<Task>>) -> String { ... }
```
[`FromForm`]: https://api.rocket.rs/rocket/request/trait.FromForm.html
[`FromFormValue`]: https://api.rocket.rs/rocket/request/trait.FromFormValue.html
[`FromForm`]: @api/v0.3/rocket/request/trait.FromForm.html
[`FromFormValue`]: @api/v0.3/rocket/request/trait.FromFormValue.html
#### Lenient Parsing
@ -556,7 +556,7 @@ struct Task { .. }
fn new(task: LenientForm<Task>) { .. }
```
[`LenientForm`]: https://api.rocket.rs/rocket/request/struct.LenientForm.html
[`LenientForm`]: @api/v0.3/rocket/request/struct.LenientForm.html
#### Field Renaming
@ -621,14 +621,14 @@ struct Person {
}
```
The [forms validation](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/form_validation)
and [forms kitchen sink](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/form_kitchen_sink)
The [forms validation](@git/v0.3/examples/form_validation)
and [forms kitchen sink](@git/v0.3/examples/form_kitchen_sink)
examples on GitHub provide further illustrations.
### JSON
Handling JSON data is no harder: simply use the
[`Json`](https://api.rocket.rs/rocket_contrib/struct.Json.html) type:
[`Json`](@api/v0.3/rocket_contrib/struct.Json.html) type:
```rust
#[derive(Deserialize)]
@ -645,13 +645,13 @@ The only condition is that the generic type in `Json` implements the
`Deserialize` trait from [Serde](https://github.com/serde-rs/json). See the
[JSON example] on GitHub for a complete example.
[JSON example]: https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/json
[JSON example]: @git/v0.3/examples/json
### Streaming
Sometimes you just want to handle incoming data directly. For example, you might
want to stream the incoming data out to a file. Rocket makes this as simple as
possible via the [`Data`](https://api.rocket.rs/rocket/data/struct.Data.html)
possible via the [`Data`](@api/v0.3/rocket/data/struct.Data.html)
type:
```rust
@ -667,7 +667,7 @@ The route above accepts any `POST` request to the `/upload` path with
response if the upload succeeds. If the upload fails, an error response is
returned. The handler above is complete. It really is that simple! See the
[GitHub example
code](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/raw_upload)
code](@git/v0.3/examples/raw_upload)
for the full crate.
## Query Strings
@ -723,14 +723,14 @@ fn new(task: Option<Task>) { ... }
For a concrete illustration on how to handle query parameters, see [the
`query_params`
example](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/query_params).
example](@git/v0.3/examples/query_params).
## Error Catchers
Routing may fail for a variety of reasons. These include:
* A [request guard](#request-guards) returns `Failure`.
* A handler returns a [`Responder`](/guide/responses/#responder) that fails.
* A handler returns a [`Responder`](../responses/#responder) that fails.
* No matching route was found.
If any of these conditions occur, Rocket returns an error to the client. To do
@ -755,10 +755,10 @@ rocket::ignite().catch(catchers![not_found])
```
Unlike request handlers, error handlers can only take 0, 1, or 2 parameters of
types [`Request`](https://api.rocket.rs/rocket/struct.Request.html) and/or
[`Error`](https://api.rocket.rs/rocket/enum.Error.html). At present, the `Error`
types [`Request`](@api/v0.3/rocket/struct.Request.html) and/or
[`Error`](@api/v0.3/rocket/enum.Error.html). At present, the `Error`
type is not particularly useful, and so it is often omitted. The [error catcher
example](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/errors) on
example](@git/v0.3/examples/errors) on
GitHub illustrates their use in full.
Rocket has a default catcher for all of the standard HTTP error codes including

View File

@ -6,7 +6,7 @@ trait can be returned, including your own. In this section, we describe the
`Responder` trait as well as several useful `Responder`s provided by Rocket.
We'll also briefly discuss how to implement your own `Responder`.
[`Responder`]: https://api.rocket.rs/rocket/response/trait.Responder.html
[`Responder`]: @api/v0.3/rocket/response/trait.Responder.html
## Responder
@ -17,7 +17,7 @@ decides which to use. For instance, `String` uses a fixed-sized body, while
`File` uses a streamed response. Responders may dynamically adjust their
responses according to the incoming `Request` they are responding to.
[`Response`]: https://api.rocket.rs/rocket/response/struct.Response.html
[`Response`]: @api/v0.3/rocket/response/struct.Response.html
### Wrapping
@ -31,7 +31,7 @@ struct WrappingResponder<R>(R);
A wrapping responder modifies the response returned by `R` before responding
with that same response. For instance, Rocket provides `Responder`s in the
[`status` module](https://api.rocket.rs/rocket/response/status/index.html) that
[`status` module](@api/v0.3/rocket/response/status/index.html) that
override the status code of the wrapped `Responder`. As an example, the
[`Accepted`] type sets the status to `202 - Accepted`. It can be used as
follows:
@ -46,7 +46,7 @@ fn new(id: usize) -> status::Accepted<String> {
```
Similarly, the types in the [`content`
module](https://api.rocket.rs/rocket/response/content/index.html) can be used to
module](@api/v0.3/rocket/response/content/index.html) can be used to
override the Content-Type of a response. For instance, to set the Content-Type
an `&'static str` to JSON, you can use the [`content::Json`] type as follows:
@ -59,14 +59,14 @@ fn json() -> content::Json<&'static str> {
}
```
[`Accepted`]: https://api.rocket.rs/rocket/response/status/struct.Accepted.html
[`content::Json`]: https://api.rocket.rs/rocket/response/content/struct.Json.html
[`Accepted`]: @api/v0.3/rocket/response/status/struct.Accepted.html
[`content::Json`]: @api/v0.3/rocket/response/content/struct.Json.html
### Errors
Responders may fail; they need not _always_ generate a response. Instead, they
can return an `Err` with a given status code. When this happens, Rocket forwards
the request to the [error catcher](/guide/requests/#error-catchers) for the
the request to the [error catcher](../requests/#error-catchers) for the
given status code.
If an error catcher has been registered for the given status code, Rocket will
@ -78,7 +78,7 @@ for a custom status code, Rocket uses the **500** error catcher to return a
response.
While not encouraged, you can also forward a request to a catcher manually by
using the [`Failure`](https://api.rocket.rs/rocket/response/struct.Failure.html)
using the [`Failure`](@api/v0.3/rocket/response/struct.Failure.html)
type. For instance, to forward to the catcher for **406 - Not Acceptable**, you
would write:
@ -181,13 +181,13 @@ many of these responders in the [`response`] module. Among these are:
* [`status`] - Contains types that override the status code of a response.
* [`Flash`] - Sets a "flash" cookie that is removed when accessed.
[`status`]: https://api.rocket.rs/rocket/response/status/index.html
[`response`]: https://api.rocket.rs/rocket/response/index.html
[`NamedFile`]: https://api.rocket.rs/rocket/response/struct.NamedFile.html
[`Content`]: https://api.rocket.rs/rocket/response/struct.Content.html
[`Redirect`]: https://api.rocket.rs/rocket/response/struct.Redirect.html
[`Stream`]: https://api.rocket.rs/rocket/response/struct.Stream.html
[`Flash`]: https://api.rocket.rs/rocket/response/struct.Flash.html
[`status`]: @api/v0.3/rocket/response/status/index.html
[`response`]: @api/v0.3/rocket/response/index.html
[`NamedFile`]: @api/v0.3/rocket/response/struct.NamedFile.html
[`Content`]: @api/v0.3/rocket/response/struct.Content.html
[`Redirect`]: @api/v0.3/rocket/response/struct.Redirect.html
[`Stream`]: @api/v0.3/rocket/response/struct.Stream.html
[`Flash`]: @api/v0.3/rocket/response/struct.Flash.html
### Streaming
@ -205,7 +205,7 @@ fn stream() -> io::Result<Stream<UnixStream>> {
```
[`rocket_contrib`]: https://api.rocket.rs/rocket_contrib/index.html
[`rocket_contrib`]: @api/v0.3/rocket_contrib/index.html
### JSON
@ -233,10 +233,10 @@ fails, a **500 - Internal Server Error** is returned.
The [JSON example on GitHub] provides further illustration.
[`JSON`]: https://api.rocket.rs/rocket_contrib/struct.Json.html
[`JSON`]: @api/v0.3/rocket_contrib/struct.Json.html
[`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html
[`serde`]: https://docs.serde.rs/serde/
[JSON example on GitHub]: https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/json
[JSON example on GitHub]: @git/v0.3/examples/json
### Templates
@ -264,7 +264,7 @@ example, if a file ends with `.hbs`, Handlebars is used, while if a file ends
with `.tera`, Tera is used.
For templates to be properly registered, the template fairing must be attached
to the instance of Rocket. The [Fairings](/guide/fairings) sections of the guide
to the instance of Rocket. The [Fairings](../fairings/) sections of the guide
provides more information on fairings. To attach the template fairing, simply
call `.attach(Template::fairing())` on an instance of `Rocket` as follows:
@ -279,7 +279,7 @@ fn main() {
The [`Template`] API
documentation contains more information about templates, while the [Handlebars
Templates example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/handlebars_templates)
GitHub](@git/v0.3/examples/handlebars_templates)
is a fully composed application that makes use of Handlebars templates.
[`Template`]: https://api.rocket.rs/rocket_contrib/struct.Template.html
[`Template`]: @api/v0.3/rocket_contrib/struct.Template.html

View File

@ -22,7 +22,7 @@ The process for using managed state is simple:
### Adding State
To instruct Rocket to manage state for your application, call the
[`manage`](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage) method
[`manage`](@api/v0.3/rocket/struct.Rocket.html#method.manage) method
on an instance of `Rocket`. For example, to ask Rocket to manage a `HitCount`
structure with an internal `AtomicUsize` with an initial value of `0`, we can
write the following:
@ -48,8 +48,8 @@ rocket::ignite()
### Retrieving State
State that is being managed by Rocket can be retrieved via the
[`State`](https://api.rocket.rs/rocket/struct.State.html) type: a [request
guard](/guide/requests/#request-guards) for managed state. To use the request
[`State`](@api/v0.3/rocket/struct.State.html) type: a [request
guard](../requests/#request-guards) for managed state. To use the request
guard, add a `State<T>` type to any request handler, where `T` is the type of
the managed state. For example, we can retrieve and respond with the current
`HitCount` in a `count` route as follows:
@ -83,7 +83,7 @@ fn from_request(req: &'a Request<'r>) -> request::Outcome<T, ()> {
}
```
[`Request::guard()`]: https://api.rocket.rs/rocket/struct.Request.html#method.guard
[`Request::guard()`]: @api/v0.3/rocket/struct.Request.html#method.guard
### Unmanaged State
@ -142,10 +142,10 @@ globally, add `#![allow(unmanaged_state)]` to your crate attributes.
You can find a complete example using the `HitCount` structure in the [state
example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/state) and
GitHub](@git/v0.3/examples/state) and
learn more about the [`manage`
method](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage) and
[`State` type](https://api.rocket.rs/rocket/struct.State.html) in the API docs.
method](@api/v0.3/rocket/struct.Rocket.html#method.manage) and
[`State` type](@api/v0.3/rocket/struct.State.html) in the API docs.
## Databases
@ -172,7 +172,7 @@ fn handler(conn: DbConn) { ... }
To get started, we need to depend on the `diesel` and `r2d2` crates. For
detailed information on how to use Diesel, please see the [Diesel getting
started guide](http://diesel.rs/guides/getting-started/). For this example, we
started guide](http://diesel.rs/getting-started/). For this example, we
use the following dependencies:
```

View File

@ -33,10 +33,10 @@ _unless_ the authentication or authorization applies to all or most of the
application. On the other hand, you _should_ use a fairing to record timing and
usage statistics or to enforce global security policies.
[`Fairing`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html
[request guard]: /guide/requests/#request-guards
[request guards]: /guide/requests/#request-guards
[data guards]: /guide/requests/#body-data
[`Fairing`]: @api/v0.3/rocket/fairing/trait.Fairing.html
[request guard]: ../requests/#request-guards
[request guards]: ../requests/#request-guards
[data guards]: ../requests/#body-data
### Attaching
@ -52,8 +52,8 @@ rocket::ignite()
.launch();
```
[`attach`]: https://api.rocket.rs/rocket/struct.Rocket.html#method.attach
[`Rocket`]: https://api.rocket.rs/rocket/struct.Rocket.html
[`attach`]: @api/v0.3/rocket/struct.Rocket.html#method.attach
[`Rocket`]: @api/v0.3/rocket/struct.Rocket.html
Fairings are executed in the order in which they are attached: the first
attached fairing has its callbacks executed before all others. Because fairing
@ -68,7 +68,7 @@ events is described below:
* **Attach (`on_attach`)**
An attach callback is called when a fairing is first attached via the
[`attach`](https://api.rocket.rs/rocket/struct.Rocket.html#method.attach)
[`attach`](@api/v0.3/rocket/struct.Rocket.html#method.attach)
method. An attach callback can arbitrarily modify the `Rocket` instance
being constructed and optionally abort launch. Attach fairings are commonly
used to parse and validate configuration values, aborting on bad
@ -108,12 +108,12 @@ fairing and determine the set of callbacks the fairing is registering for. A
[`on_launch`], [`on_request`], and [`on_response`]. Each callback has a default
implementation that does absolutely nothing.
[`Info`]: https://api.rocket.rs/rocket/fairing/struct.Info.html
[`info`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#tymethod.info
[`on_attach`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_attach
[`on_launch`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_launch
[`on_request`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_request
[`on_response`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_response
[`Info`]: @api/v0.3/rocket/fairing/struct.Info.html
[`info`]: @api/v0.3/rocket/fairing/trait.Fairing.html#tymethod.info
[`on_attach`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_attach
[`on_launch`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_launch
[`on_request`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_request
[`on_response`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_response
### Requirements
@ -183,7 +183,7 @@ impl Fairing for Counter {
For brevity, imports are not shown. The complete example can be found in the
[`Fairing`
documentation](https://api.rocket.rs/rocket/fairing/trait.Fairing.html#example).
documentation](@api/v0.3/rocket/fairing/trait.Fairing.html#example).
## Ad-Hoc Fairings
@ -211,5 +211,5 @@ rocket::ignite()
}));
```
[`AdHoc`]: https://api.rocket.rs/rocket/fairing/enum.AdHoc.html
[`AdHoc`]: @api/v0.3/rocket/fairing/enum.AdHoc.html

View File

@ -14,32 +14,32 @@ instance. Usage is straightforward:
1. Construct a `Rocket` instance that represents the application.
```rust
let rocket = rocket::ignite();
```
```rust
let rocket = rocket::ignite();
```
2. Construct a `Client` using the `Rocket` instance.
```rust
let client = Client::new(rocket).expect("valid rocket instance");
```
```rust
let client = Client::new(rocket).expect("valid rocket instance");
```
3. Construct requests using the `Client` instance.
```rust
let req = client.get("/");
```
```rust
let req = client.get("/");
```
4. Dispatch the request to retrieve the response.
```rust
let response = req.dispatch();
```
```rust
let response = req.dispatch();
```
[`local`]: https://api.rocket.rs/rocket/local/index.html
[`Client`]: https://api.rocket.rs/rocket/local/struct.Client.html
[`LocalRequest`]: https://api.rocket.rs/rocket/local/struct.LocalRequest.html
[`Rocket`]: https://api.rocket.rs/rocket/struct.Rocket.html
[`local`]: @api/v0.3/rocket/local/index.html
[`Client`]: @api/v0.3/rocket/local/struct.Client.html
[`LocalRequest`]: @api/v0.3/rocket/local/struct.LocalRequest.html
[`Rocket`]: @api/v0.3/rocket/struct.Rocket.html
## Validating Responses
@ -57,13 +57,13 @@ a few below:
* [`body_string`]: returns the body data as a `String`.
* [`body_bytes`]: returns the body data as a `Vec<u8>`.
[`LocalResponse`]: https://api.rocket.rs/rocket/local/struct.LocalResponse.html
[`Response`]: https://api.rocket.rs/rocket/struct.Response.html
[`status`]: https://api.rocket.rs/rocket/struct.Response.html#method.status
[`content_type`]: https://api.rocket.rs/rocket/struct.Response.html#method.content_type
[`headers`]: https://api.rocket.rs/rocket/struct.Response.html#method.headers
[`body_string`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_string
[`body_bytes`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_bytes
[`LocalResponse`]: @api/v0.3/rocket/local/struct.LocalResponse.html
[`Response`]: @api/v0.3/rocket/struct.Response.html
[`status`]: @api/v0.3/rocket/struct.Response.html#method.status
[`content_type`]: @api/v0.3/rocket/struct.Response.html#method.content_type
[`headers`]: @api/v0.3/rocket/struct.Response.html#method.headers
[`body_string`]: @api/v0.3/rocket/struct.Response.html#method.body_string
[`body_bytes`]: @api/v0.3/rocket/struct.Response.html#method.body_bytes
These methods are typically used in combination with the `assert_eq!` or
`assert!` macros as follows:
@ -179,7 +179,7 @@ mod test {
The tests can be run with `cargo test`. You can find the full source code to
[this example on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/testing).
GitHub](@git/v0.3/examples/testing).
## Codegen Debug

View File

@ -131,8 +131,8 @@ incoming JSON data. You should use the `limits` parameter for your application's
data limits as well. Data limits can be retrieved at runtime via the
[`Request::limits()`] method.
[`Request::limits()`]: https://api.rocket.rs/rocket/struct.Request.html#method.limits
[`Json`]: https://api.rocket.rs/rocket_contrib/struct.Json.html#incoming-data-limits
[`Request::limits()`]: @api/v0.3/rocket/struct.Request.html#method.limits
[`Json`]: @api/v0.3/rocket_contrib/struct.Json.html#incoming-data-limits
## Extras
@ -140,7 +140,7 @@ In addition to overriding default configuration parameters, a configuration file
can also define values for any number of _extra_ configuration parameters. While
these parameters aren't used by Rocket directly, other libraries, or your own
application, can use them as they wish. As an example, the
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html) type
[Template](@api/v0.3/rocket_contrib/struct.Template.html) type
accepts a value for the `template_dir` configuration parameter. The parameter
can be set in `Rocket.toml` as follows:
@ -167,8 +167,8 @@ To retrieve a custom, extra configuration parameter in your application, we
recommend using an [ad-hoc attach fairing] in combination with [managed state].
For example, if your application makes use of a custom `assets_dir` parameter:
[ad-hoc attach fairing]: /guide/fairings/#ad-hoc-fairings
[managed state]: /guide/state/#managed-state
[ad-hoc attach fairing]: ../fairings/#ad-hoc-fairings
[managed state]: ../state/#managed-state
```toml
[development]

View File

@ -101,7 +101,7 @@ string with the specified contents. Rocket will take the string and return it as
the body of a fully formed HTTP response with `Content-Type: text/plain`. You
can read more about how Rocket formulates responses at the [API documentation
for the Responder
trait](https://api.rocket.rs/rocket/response/trait.Responder.html).
trait](@api/v0.3/rocket/response/trait.Responder.html).
Remember that routes first need to be mounted before Rocket dispatches requests
to them. To mount the `index` route, modify the main function so that it reads:
@ -214,7 +214,7 @@ use rocket::Data;
use rocket::http::RawStr;
```
The [Data](https://api.rocket.rs/rocket/data/struct.Data.html) structure is key
The [Data](@api/v0.3/rocket/data/struct.Data.html) structure is key
here: it represents an unopened stream to the incoming request body data. We'll
use it to efficiently stream the incoming request to a file.
@ -290,7 +290,7 @@ Here's a first take at implementing the `retrieve` route. The route below takes
in an `<id>` as a dynamic path element. The handler uses the `id` to construct a
path to the paste inside `upload/`, and then attempts to open the file at that
path, optionally returning the `File` if it exists. Rocket treats a `None`
[Responder](https://api.rocket.rs/rocket/response/trait.Responder.html#provided-implementations)
[Responder](@api/v0.3/rocket/response/trait.Responder.html#provided-implementations)
as a **404** error, which is exactly what we want to return when the requested
paste doesn't exist.
@ -306,7 +306,7 @@ fn retrieve(id: &RawStr) -> Option<File> {
```
Unfortunately, there's a problem with this code. Can you spot the issue? The
[`RawStr`](https://api.rocket.rs/rocket/http/struct.RawStr.html) type should tip
[`RawStr`](@api/v0.3/rocket/http/struct.RawStr.html) type should tip
you off!
The issue is that the _user_ controls the value of `id`, and as a result, can
@ -321,7 +321,7 @@ provides the tools to prevent this and other kinds of attacks from happening.
To prevent the attack, we need to _validate_ `id` before we use it. Since the
`id` is a dynamic parameter, we can use Rocket's
[FromParam](https://api.rocket.rs/rocket/request/trait.FromParam.html) trait to
[FromParam](@api/v0.3/rocket/request/trait.FromParam.html) trait to
implement the validation and ensure that the `id` is a valid `PasteID` before
using it. We do this by implementing `FromParam` for `PasteID` in
`src/paste_id.rs`, as below:
@ -399,10 +399,10 @@ through some of them to get a better feel for Rocket. Here are some ideas:
* Add a new route, `GET /<id>/<lang>` that syntax highlights the paste with ID
`<id>` for language `<lang>`. If `<lang>` is not a known language, do no
highlighting. Possibly validate `<lang>` with `FromParam`.
* Use the [`local` module](https://api.rocket.rs/rocket/local/) to write
* Use the [`local` module](@api/v0.3/rocket/local/) to write
unit tests for your pastebin.
* Dispatch a thread before `launch`ing Rocket in `main` that periodically
cleans up idling old pastes in `upload/`.
You can find the full source code for the [completed pastebin tutorial on
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/pastebin).
GitHub](@git/v0.3/examples/pastebin).

View File

@ -22,7 +22,7 @@ guide.
The best way to learn Rocket is to _build something_. It should be fun and easy,
and there's always someone to help. Alternatively, you can read through the
[Rocket examples](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples)
[Rocket examples](@git/v0.3/examples)
or the [Rocket source
code](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/lib/src). Whatever you
code](@git/v0.3/lib/src). Whatever you
decide to do next, we hope you have a blast!

View File

@ -6,7 +6,7 @@ This is the official guide. It is designed to serve as a starting point to
writing web applications with Rocket and Rust. The guide is also designed to be
a reference for experienced Rocket developers. This guide is conversational in
tone. For concise and purely technical documentation, see the [API
documentation](https://api.rocket.rs).
documentation](@api/v0.3).
The guide is split into several sections, each with a focus on a different
aspect of Rocket. The sections are:

View File

@ -1,27 +0,0 @@
# Rocket Website Source
This directory contains the source files for the content on [Rocket's
website](https://rocket.rs).
## Contents
This directory contains the following:
* `index.toml` - Source data for the index (`/`).
* `news.toml` - Source data for the news page (`/news`).
* `overview.toml` - Source data for the overview page (`/overview`).
* `guide.md` - Index page for the [Rocket Programming Guide] (`/guide`).
* `news/*.md` - News articles linked to from `news.toml`.
* `guide/*.md` - Guide pages linked to from `guide.md`.
[Rocket Programming Guide]: https://rocket.rs/guide/
### Guide Links
Cross-linking to pages in the guide is accomplished via absolute links rooted at
`/guide/`. To link to the page whose source is at `guide/page.md`, for instance,
link to `/guide/page`.
## License
The Rocket website source is licensed under the [GNU General Public License v3.0](LICENSE).

View File

@ -1,193 +0,0 @@
###############################################################################
# Top features: displayed in the header under the introductory text.
###############################################################################
[release]
url = "https://crates.io/crates/rocket"
version = "0.3.17"
date = "Sep 29, 2018"
[[top_features]]
title = "Type Safe"
text = "From request to response Rocket ensures that your types mean something."
image = "helmet"
button = "Learn More"
url = "/overview/#how-rocket-works"
[[top_features]]
title = "Boilerplate Free"
text = "Spend your time writing code that really matters, and let Rocket generate the rest."
image = "robot-free"
button = "See Examples"
url = "/overview/#anatomy-of-a-rocket-application"
[[top_features]]
title = "Easy To Use"
text = "Rocket makes extensive use of Rust's code generation tools to provide a clean API."
image = "sun"
button = "Get Started"
url = "/guide"
margin = 2
[[top_features]]
title = "Extensible"
text = "Easily create your own primitives that any Rocket application can use."
image = "telescope"
button = "See How"
url = "/overview/#anatomy-of-a-rocket-application"
margin = 9
###############################################################################
# Sections: make sure there are an odd number so colors work out.
###############################################################################
[[sections]]
title = "Hello, Rocket!"
code = '''
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/hello/<name>/<age>")]
fn hello(name: String, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
fn main() {
rocket::ignite().mount("/", routes![hello]).launch();
}
'''
text = '''
This is a **complete Rocket application**. It does exactly what you would
expect. If you were to visit **http://localhost:8000/hello/John/58**, youd
see:
<span class="callout">Hello, 58 year old named John!</span>
If someone visits a path with an `<age>` that isnt a `u8`, Rocket doesnt
blindly call `hello`. Instead, it tries other matching routes or returns a
**404**.
'''
[[sections]]
title = "Forms? Check!"
code = '''
#[derive(FromForm)]
struct Task {
description: String,
completed: bool
}
#[post("/", data = "<task>")]
fn new(task: Form<Task>) -> Flash<Redirect> {
if task.get().description.is_empty() {
Flash::error(Redirect::to("/"), "Cannot be empty.")
} else {
Flash::success(Redirect::to("/"), "Task added.")
}
}
'''
text = '''
Handling forms **is simple and easy**. Simply derive `FromForm` for your
structure and let Rocket know which parameter to use. Rocket **parses and
validates** the form request, creates the structure, and calls your function.
Bad form request? Rocket doesnt call your function! What if you want to know
if the form was bad? Simple! Change the type of `task` to `Option` or
`Result`!
'''
[[sections]]
title = "JSON, out of the box."
code = '''
#[derive(Serialize, Deserialize)]
struct Message {
contents: String,
}
#[put("/<id>", data = "<message>")]
fn update(id: ID, message: Json<Message>) -> Json<Value> {
if DB.contains_key(&id) {
DB.insert(id, &message.contents);
Json(json!{ "status": "ok" })
} else {
Json(json!{ "status": "error" })
}
}
'''
text = '''
Rocket has first-class support for JSON, right out of the box. Simply derive
`Deserialize` or `Serialize` to receive or return JSON, respectively.
Like other important features, JSON works through Rockets `FromData` trait,
Rockets approach to deriving types from body data. It works like this:
specify a `data` route parameter of any type that implements `FromData`. A
value of that type will then be created automatically from the incoming
request body. Best of all, you can implement `FromData` for your types!
'''
###############################################################################
# Buttom features: displayed above the footer.
###############################################################################
[[bottom_features]]
title = 'Templating'
text = "Rocket makes rendering templates a breeze with built-in templating support."
image = 'templating-icon'
url = '/guide/responses/#templates'
button = 'Learn More'
color = 'blue'
[[bottom_features]]
title = 'Cookies'
text = "View, add, or remove cookies, with or without encryption, without hassle."
image = 'cookies-icon'
url = '/guide/requests/#cookies'
button = 'Learn More'
color = 'purple'
margin = -6
[[bottom_features]]
title = 'Streams'
text = "Rocket streams all incoming and outgoing data, so size isn't a concern."
image = 'streams-icon'
url = '/guide/requests/#streaming'
button = 'Learn More'
color = 'red'
margin = -29
[[bottom_features]]
title = 'Config Environments'
text = "Configure your application your way for development, staging, and production."
image = 'config-icon'
url = '/guide/configuration/#environment'
button = 'Learn More'
color = 'yellow'
margin = -3
[[bottom_features]]
title = 'Query Strings'
text = "Handling query strings and parameters is type-safe and easy in Rocket."
image = 'query-icon'
url = '/guide/requests/#query-strings'
button = 'Learn More'
color = 'orange'
margin = -3
[[bottom_features]]
title = 'Testing Library'
text = "Unit test your applications with ease using the built-in testing library."
image = 'testing-icon'
url = '/guide/testing#testing'
button = 'Learn More'
color = 'green'
# Blocked on Hyper/OpenSSL.
# [[bottom_features]]
# title = 'Signed Sessions'
# text = "Safe, secure, signed sessions are built-in to Rocket so your users can stay safe."
# image = 'sessions-icon'
# url = '/overview'
# button = 'Learn More'
# color = 'green'

View File

@ -1,33 +0,0 @@
[[articles]]
title = "Rocket v0.3: Fairings, TLS, Private Cookies"
slug = "2017-07-14-version-0.3"
author = "Sergio Benitez"
author_url = "https://sergio.bz"
date = "July 14, 2017"
snippet = """
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!
"""
[[articles]]
title = "Rocket v0.2: Managed State & More"
slug = "2017-02-06-version-0.2"
author = "Sergio Benitez"
author_url = "https://sergio.bz"
date = "February 06, 2017"
snippet = """
Today marks the first major release since Rocket's debut a little over a month
ago. Rocket v0.2 packs a ton of new features, fixes, and general improvements.
Much of the development in v0.2 was led by the community, either through reports
via the [GitHub issue tracker](https://github.com/SergioBenitez/Rocket/issues)
or via direct contributions. In fact, there have been **20 unique contributors**
to Rocket's codebase since Rocket's initial introduction! Community feedback has
been incredible. As a special thank you, we include the names of these
contributors at the end of this article.
"""

View File

@ -1,396 +0,0 @@
# Rocket v0.2: Managed State & More
<p class="metadata"><strong>
Posted by <a href="https://sergio.bz">Sergio Benitez</a> on February 06, 2017
</strong></p>
<!-- we should be able to generate the title and subheading -->
Today marks the first major release since Rocket's debut a little over a month
ago. Rocket v0.2 packs a ton of new features, fixes, and general improvements.
Much of the development in v0.2 was led by the community, either through reports
via the [GitHub issue tracker](https://github.com/SergioBenitez/Rocket/issues)
or via direct contributions. In fact, there have been **20 unique contributors**
to Rocket's codebase since Rocket's initial introduction! Community feedback has
been incredible. As a special thank you, we include the names of these
contributors at the end of this article.
## 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.
> Rocket's so simple, you feel like you're doing something wrong. It's like if
> you're making fire with rocks and suddenly someone gives you a lighter. Even
> though you know the lighter makes fire, and does it even faster and better and
> with a simple flick, the rock's still in your brain.
>
> -- <cite>Artem "impowski" Biryukov, January 17, 2017, on **#rocket**</cite>
## New Features
Rocket v0.2 includes several new features that make developing Rocket
applications simpler, faster, and safer than ever before.
### Managed State
Undoubtedly, the star feature of this release is **managed state**. Managed
state allows you to pass state to Rocket prior to launching your application and
later retrieve that state from any request handler by simply including the
state's type in the function signature. It works in two easy steps:
1. Call `manage` on the `Rocket` instance corresponding to your application
with the initial value of the state.
2. Add a `State<T>` type to any request handler, where `T` is the type of the
value passed into `manage`.
Rocket takes care of the rest! `State` works through Rocket's [request
guards](/guide/requests/#request-guards). You can call `manage` any number of
times, as long as each call corresponds to a value of a different type.
As a simple example, consider the following "hit counter" example application:
```rust
struct HitCount(AtomicUsize);
#[get("/")]
fn index(hit_count: State<HitCount>) -> &'static str {
hit_count.0.fetch_add(1, Ordering::Relaxed);
"Your visit has been recorded!"
}
#[get("/count")]
fn count(hit_count: State<HitCount>) -> String {
hit_count.0.load(Ordering::Relaxed).to_string()
}
fn main() {
rocket::ignite()
.mount("/", routes![index, count])
.manage(HitCount(AtomicUsize::new(0)))
.launch()
}
```
Visiting `/` will record a visit by incrementing the hit count by 1. Visiting
the `/count` path will display the current hit count.
One concern when using _managed state_ is that you might forget to call `manage`
with some state's value before launching your application. Not to worry: Rocket
has your back! Let's imagine for a second that we forgot to add the call to
`manage` on line 17 in the example above. Here's what the compiler would emit
when we compile our buggy application:
```rust
warning: HitCount is not currently being managed by Rocket
--> src/main.rs:4:21
|
4 | fn index(hit_count: State<HitCount>) -> &'static str {
| ^^^^^^^^^^^^^^^
|
= note: this State request guard will always fail
help: maybe add a call to 'manage' here?
--> src/main.rs:15:5
|
15| rocket::ignite()
| ^^^^^^^^^^^^^^^^
warning: HitCount is not currently being managed by Rocket
--> src/main.rs:10:21
|
10 | fn count(hit_count: State<HitCount>) -> String {
| ^^^^^^^^^^^^^^^
|
= note: this State request guard will always fail
help: maybe add a call to 'manage' here?
--> src/main.rs:15:5
|
15 | rocket::ignite()
| ^^^^^^^^^^^^^^^^
```
You can read more about managed state in the [guide](/guide/state/), the API
docs for
[manage](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage), and the
API docs for [State](https://api.rocket.rs/rocket/struct.State.html).
### Unmounted Routes Lint
A common mistake that new Rocketeers make is forgetting to
[mount](/guide/overview/#mounting) declared routes. In Rocket v0.2, Rocket adds
a _lint_ that results in a compile-time warning for unmounted routes. As a
simple illustration, consider the canonical "Hello, world!" Rocket application
below, and note that we've forgotten to mount the `hello` route:
```rust
#[get("/")]
fn hello() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().launch();
}
```
When this program is compiled, the compiler emits the following warning:
```rust
warning: the 'hello' route is not mounted
--> src/main.rs:2:1
|
2 | fn hello() -> &'static str {
| _^ starting here...
3 | | "Hello, world!"
4 | | }
| |_^ ...ending here
|
= note: Rocket will not dispatch requests to unmounted routes.
help: maybe add a call to 'mount' here?
--> src/main.rs:7:5
|
7 | rocket::ignite().launch();
| ^^^^^^^^^^^^^^^^
```
The lint can be disabled selectively per route by adding an
`#[allow(unmounted_route)]` annotation to a given route declaration. It can also
be disabled globally by adding `#![allow(unmounted_route)]`. You can read more
about this lint in the [codegen
documentation](https://api.rocket.rs/rocket_codegen/index.html).
### Configuration via Environment Variables
A new feature that makes deploying Rocket apps to the cloud a little easier is
configuration via environment variables. Simply put, any configuration parameter
can be set via an environment variable of the form `ROCKET_{PARAM}`, where
`{PARAM}` is the name of the configuration parameter. For example, to set the
`port` Rocket listens on, simply set the `ROCKET_PORT` environment variable:
```sh
ROCKET_PORT=3000 cargo run --release
```
Configuration parameters set via environment variables take precedence over
parameters set via the `Rocket.toml` configuration file. Note that _any_
parameter can be set via an environment variable, include _extras_. For more
about configuration in Rocket, see the [configuration section of the
guide](/guide/overview/#configuration).
### And Plenty More!
Rocket v0.2 is full of many new features! In addition to the three features
described above, v0.2 also includes the following:
* `Config` structures can be built via `ConfigBuilder`, which follows the
builder pattern.
* Logging can be enabled or disabled on custom configuration via a second
parameter to the `Rocket::custom` method.
* `name` and `value` methods were added to `Header` to retrieve the name and
value of a header.
* A new configuration parameter, `workers`, can be used to set the number of
threads Rocket uses.
* The address of the remote connection is available via `Request.remote()`.
Request preprocessing overrides remote IP with value from the `X-Real-IP`
header, if present.
* During testing, the remote address can be set via `MockRequest.remote()`.
* The `SocketAddr` request guard retrieves the remote address.
* A `UUID` type has been added to `contrib`.
* `rocket` and `rocket_codegen` will refuse to build with an incompatible
nightly version and emit nice error messages.
* Major performance and usability improvements were upstreamed to the `cookie`
crate, including the addition of a `CookieBuilder`.
* When a checkbox isn't present in a form, `bool` types in a `FromForm`
structure will parse as `false`.
* The `FormItems` iterator can be queried for a complete parse via `completed`
and `exhausted`.
* Routes for `OPTIONS` requests can be declared via the `options` decorator.
* Strings can be percent-encoded via `URI::percent_encode()`.
## Breaking Changes
This release includes several breaking changes. These changes are listed below
along with a short note about how to handle the breaking change in existing
applications.
* **`Rocket::custom` takes two parameters, the first being `Config` by
value.**
A call in v0.1 of the form `Rocket::custom(&config)` is now
`Rocket::custom(config, false)`.
* **Tera templates are named without their extension.**
A templated named `name.html.tera` is now simply `name`.
* **`JSON` `unwrap` method has been renamed to `into_inner`.**
A call to `.unwrap()` should be changed to `.into_inner()`.
* **The `map!` macro was removed in favor of the `json!` macro.**
A call of the form `map!{ "a" => b }` can be written as: `json!({ "a": b
})`.
* **The `hyper::SetCookie` header is no longer exported.**
Use the `Cookie` type as an `Into<Header>` type directly.
* **The `Content-Type` for `String` is now `text/plain`.**
Use `content::HTML<String>` for HTML-based `String` responses.
* **`Request.content_type()` returns an `Option<ContentType>`.**
Use `.unwrap_or(ContentType::Any)` to get the old behavior.
* **The `ContentType` request guard forwards when the request has no
`Content-Type` header.**
Use an `Option<ContentType>` and `.unwrap_or(ContentType::Any)` for the old
behavior.
* **A `Rocket` instance must be declared _before_ a `MockRequest`.**
Change the order of the `rocket::ignite()` and `MockRequest::new()` calls.
* **A route with `format` specified only matches requests with the same
format.**
Previously, a route with a `format` would match requests without a format
specified. There is no workaround to this change; simply specify formats
when required.
* **`FormItems` can no longer be constructed directly.**
Instead of constructing as `FormItems(string)`, construct as
`FormItems::from(string)`.
* **`from_from_string(&str)` in `FromForm` removed in favor of
`from_form_items(&mut FormItems)`.**
Most implementation should be using `FormItems` internally; simply use the
passed in `FormItems`. In other cases, the form string can be retrieved via
the `inner_str` method of `FormItems`.
* **`Config::{set, default_for}` are deprecated.**
Use the `set_{param}` methods instead of `set`, and `new` or `build` in
place of `default_for`.
* **Route paths must be absolute.**
Prepend a `/` to convert a relative path into an absolute one.
* **Route paths cannot contain empty segments.**
Remove any empty segments, including trailing ones, from a route path.
## Bug Fixes
Three bugs were fixed in this release:
* Handlebars partials were not properly registered
([#122](https://github.com/SergioBenitez/Rocket/issues/122)).
* `Rocket::custom` did not set the custom configuration as the `active`
configuration.
* Route path segments with more than one dynamic parameter were erroneously
allowed.
## General Improvements
In addition to new features, Rocket saw the following smaller improvements:
* Rocket no longer overwrites a catcher's response status.
* The `port` `Config` type is now a proper `u16`.
* Clippy issues injected by codegen are resolved.
* Handlebars was updated to `0.25`.
* The `PartialEq` implementation of `Config` doesn't consider the path or
session key.
* Hyper dependency updated to `0.10`.
* The `Error` type for `JSON as FromData` has been exposed as `SerdeError`.
* SVG was added as a known Content-Type.
* Serde was updated to `0.9`.
* Form parse failure now results in a **422** error code.
* Tera has been updated to `0.7`.
* `pub(crate)` is used throughout to enforce visibility rules.
* Query parameters in routes (`/path?<param>`) are now logged.
* Routes with and without query parameters no longer _collide_.
Rocket v0.2 also includes all of the new features, bug fixes, and improvements
from versions 0.1.1 through 0.1.6. You can read more about these changes in the
[v0.1
CHANGELOG](https://github.com/SergioBenitez/Rocket/blob/v0.1/CHANGELOG.md).
## What's next?
Work now begins on Rocket v0.3! The focus of the next major release will be on
security. In particular, three major security features are planned:
1. **Automatic CSRF protection across all payload-based requests
([#14](https://github.com/SergioBenitez/Rocket/issues/14)).**
Rocket will automatically check the origin of requests made for HTTP `PUT`,
`POST`, `DELETE`, and `PATCH` requests, allowing only authorized requests to
be dispatched. This includes checking `POST`s from form submissions and any
requests made via JavaScript.
2. **Encryption and signing of session-based cookies
([#20](https://github.com/SergioBenitez/Rocket/issues/20)).**
Built-in session support will encrypt and sign cookies using a user supplied
`session_key`. Encryption and signing will occur automatically for
session-based cookies.
3. **Explicit typing of raw HTTP data strings
([#43](https://github.com/SergioBenitez/Rocket/issues/43)).**
A present, the standard `&str` type is used to represent raw HTTP data
strings. In the next release, a new type, `&RawStr`, will be used for this
purpose. This will make it clear when raw data is being handled. The type
will expose convenient methods such as `.url_decode()` and `.html_escape()`.
Work on Rocket v0.3 will also involve exploring built-in support for user
authentication and authorization as well as automatic parsing of multipart
forms.
## Contributors to v0.2
The following wonderful people helped make Rocket v0.2 happen:
<ul class="columns">
<li>Cliff H</li>
<li>Dru Sellers</li>
<li>Eijebong</li>
<li>Eric D. Reichert</li>
<li>Ernestas Poskus</li>
<li>FliegendeWurst</li>
<li>Garrett Squire</li>
<li>Giovanni Capuano</li>
<li>Greg Edwards</li>
<li>Joel Roller</li>
<li>Josh Holmer</li>
<li>Liigo Zhuang</li>
<li>Lori Holden</li>
<li>Marcus Ball</li>
<li>Matt McCoy</li>
<li>Reilly Tucker Siemens</li>
<li>Robert Balicki</li>
<li>Sean Griffin</li>
<li>Seth Lopez</li>
<li>tborsa</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!
## Start using Rocket today!
Not already using Rocket? Rocket is extensively documented, making it easy for
you to start writing your web applications in Rocket! See the
[overview](/overview) or start writing code immediately by reading through [the
guide](/guide).

View File

@ -1,331 +0,0 @@
# Rocket v0.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 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, 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 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/SergioBenitez/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`]: 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 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<u8>`.
* [`Response::content_type()`] was added to retrieve the Content-Type header
of a response.
* Data limits on incoming data are [now
configurable](/guide/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<T: FromForm>`, `Result<T: FromForm,
T::Error>`.
* The [`NotFound`] responder was added for simple **404** response
construction.
[`MsgPack`]: https://api.rocket.rs/rocket_contrib/struct.MsgPack.html
[`Rocket::launch()`]: https://api.rocket.rs/rocket/struct.Rocket.html#method.launch
[`LaunchError`]: https://api.rocket.rs/rocket/error/struct.LaunchError.html
[Default rankings]: https://api.rocket.rs/rocket/struct.Route.html
[`&Route`]: https://api.rocket.rs/rocket/struct.Route.html
[`Route`]: https://api.rocket.rs/rocket/struct.Route.html
[`Accept`]: https://api.rocket.rs/rocket/http/struct.Accept.html
[`Request::accept()`]: https://api.rocket.rs/rocket/struct.Request.html#method.accept
[`contrib`]: https://api.rocket.rs/rocket_contrib/
[`Rocket::routes()`]: https://api.rocket.rs/rocket/struct.Rocket.html#method.routes
[`Response::body_string()`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_string
[`Response::body_bytes()`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_bytes
[`Response::content_type()`]: https://api.rocket.rs/rocket/struct.Response.html#method.content_type
[`Request::guard()`]: https://api.rocket.rs/rocket/struct.Request.html#method.guard
[`Request::limits()`]: https://api.rocket.rs/rocket/struct.Request.html#method.limits
[`Request::route()`]: https://api.rocket.rs/rocket/struct.Request.html#method.route
[`Config`]: https://api.rocket.rs/rocket/struct.Config.html
[`Cookies`]: https://api.rocket.rs/rocket/http/enum.Cookies.html
[`Config::get_datetime()`]: https://api.rocket.rs/rocket/struct.Config.html#method.get_datetime
[`LenientForm`]: https://api.rocket.rs/rocket/request/struct.LenientForm.html
[configuration parameters]: https://api.rocket.rs/rocket/config/index.html#environment-variables
[`NotFound`]: https://api.rocket.rs/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/SergioBenitez/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<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!

View File

@ -1,232 +0,0 @@
###############################################################################
# Panels: displayed in a tabbed arrangement.
###############################################################################
[[panels]]
name = "Routing"
checked = true
content = '''
Rocket's main task is to route incoming requests to the appropriate request
handler using your application's declared routes. Routes are declared using
Rocket's _route_ attributes. The attribute describes the requests that match the
route. The attribute is placed on top of a function that is the request handler
for that route.
As an example, consider the simple route below:
```rust
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
```
This route, named `index`, will match against incoming HTTP `GET` requests to
the `/` path, the index. The request handler returns a string. Rocket will use
the string as the body of a fully formed HTTP response.
'''
[[panels]]
name = "Dynamic Params"
content = '''
Rocket allows you to interpret segments of a request path dynamically. To
illustrate, let's use the following route:
```rust
#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
```
The `hello` route above matches two dynamic path segments declared inside
brackets in the path: `<name>` and `<age>`. _Dynamic_ means that the segment can
be _any_ value the end-user desires.
Each dynamic parameter (`name` and `age`) must have a type, here `&str` and
`u8`, respectively. Rocket will attempt to parse the string in the parameter's
position in the path into that type. The route will only be called if parsing
succeeds. To parse the string, Rocket uses the
[FromParam](https://api.rocket.rs/rocket/request/trait.FromParam.html) trait,
which you can implement for your own types!
'''
[[panels]]
name = "Handling Data"
content = '''
Request body data is handled in a special way in Rocket: via the
[FromData](https://api.rocket.rs/rocket/data/trait.FromData.html) trait. Any
type that implements `FromData` can be derived from incoming body data. To tell
Rocket that you're expecting request body data, the `data` route argument is
used with the name of the parameter in the request handler:
```rust
#[post("/login", data = "<user_form>")]
fn login(user_form: Form<UserLogin>) -> String {
// Use `user_form`, return a String.
}
```
The `login` route above says that it expects `data` of type `Form<UserLogin>` in
the `user_form` parameter. The
[Form](https://api.rocket.rs/rocket/request/struct.Form.html) type is a built-in
Rocket type that knows how to parse web forms into structures. Rocket will
automatically attempt to parse the request body into the `Form` and call the
`login` handler if parsing succeeds. Other built-in `FromData` types include
[`Data`](https://api.rocket.rs/rocket/struct.Data.html),
[`Json`](https://api.rocket.rs/rocket_contrib/struct.Json.html), and
[`Flash`](https://api.rocket.rs/rocket/response/struct.Flash.html)
'''
[[panels]]
name = "Request Guards"
content = '''
In addition to dynamic path and data parameters, request handlers can also
contain a third type of parameter: _request guards_. Request guards aren't
declared in the route attribute, and any number of them can appear in the
request handler signature.
Request guards _protect_ the handler from running unless some set of conditions
are met by the incoming request metadata. For instance, if you are writing an
API that requires sensitive calls to be accompanied by an API key in the request
header, Rocket can protect those calls via a custom `ApiKey` request guard:
```rust
#[get("/sensitive")]
fn sensitive(key: ApiKey) -> &'static str { ... }
```
`ApiKey` protects the `sensitive` handler from running incorrectly. In order for
Rocket to call the `sensitive` handler, the `ApiKey` type needs to be derived
through a
[FromRequest](https://api.rocket.rs/rocket/request/trait.FromRequest.html)
implementation, which in this case, validates the API key header. Request guards
are a powerful and unique Rocket concept; they centralize application policy and
invariants through types.
'''
[[panels]]
name = "Responders"
content = '''
The return type of a request handler can be any type that implements
[Responder](https://api.rocket.rs/rocket/response/trait.Responder.html):
```rust
#[get("/")]
fn route() -> T { ... }
```
Above, T must implement `Responder`. Rocket implements `Responder` for many of
the standard library types including `&str`, `String`, `File`, `Option`, and
`Result`. Rocket also implements custom responders such as
[Redirect](https://api.rocket.rs/rocket/response/struct.Redirect.html),
[Flash](https://api.rocket.rs/rocket/response/struct.Flash.html), and
[Template](https://api.rocket.rs/rocket_contrib/struct.Template.html).
The task of a `Responder` is to generate a
[`Response`](https://api.rocket.rs/rocket/response/struct.Response.html), if
possible. `Responder`s can fail with a status code. When they do, Rocket calls
the corresponding error catcher, a `catch` route, which can be declared as
follows:
```rust
#[catch(404)]
fn not_found() -> T { ... }
```
'''
[[panels]]
name = "Launching"
content = '''
Launching a Rocket application is the funnest part! For Rocket to begin
dispatching requests to routes, the routes need to be _mounted_. After mounting,
the application needs to be _launched_. These two steps, usually done in `main`,
look like:
```rust
rocket::ignite()
.mount("/base", routes![index, another])
.launch()
```
The `mount` call takes a base path and a set of routes via the `routes!` macro.
The base path (`/base` above) is prepended to the path of every route in the
list. This effectively namespaces the routes, allowing for easier composition.
The `launch` call starts the server. In development, Rocket prints useful
information to the console to let you know everything is okay.
```sh
🚀 Rocket has launched from http://localhost:8000...
```
'''
###############################################################################
# Steps to "How Rocket Works"
###############################################################################
[[steps]]
name = "Validation"
color = "blue"
content = '''
First, Rocket validates a matching request by ensuring that all of the types in
a given handler can be derived from the incoming request. If the types cannot be
derived, the request is forwarded to the next matching route until a routes
types validate or there are no more routes to try. If all routes fail, a
customizable **404** error is returned.
```rust
#[post("/user", data = "<new_user>")]
fn new_user(admin: AdminUser, new_user: Form<User>) -> T {
...
}
```
For the `new_user` handler above to be called, the following conditions must
hold:
* The request method must be `POST`.
* The request path must be `/user`.
* The request must contain `data` in its body.
* The request metadata must authenticate an `AdminUser`.
* The request body must be a form that parses into a `User` struct.
'''
[[steps]]
name = "Processing"
color = "purple"
content = '''
Next, the request is processed by an arbitrary handler. This is where most of
the business logic in an application resides, and the part of your applications
youll likely spend the most time writing. In Rocket, handlers are simply
functions - thats it! The only caveat is that the functions return type must
implement the `Responder` trait. The `new_user` function above is an example of
a handler.
'''
[[steps]]
name = "Response"
color = "red"
content = '''
Finally, Rocket responds to the client by transforming the return value of the
handler into an HTTP response. The HTTP response generated from the returned
value depends on the types specific `Responder` trait implementation.
```rust
fn route() -> T { ... }
```
If the function above is used as a handler, for instance, then the type `T` must
implement `Responder`. Rocket provides many useful responder types out of the
box. They include:
* `Json<T>`: Serializes the structure T into JSON and returns it to
the client.
* `Template`: Renders a template file and returns it to the client.
* `Redirect`: Returns a properly formatted HTTP redirect.
* `NamedFile`: Streams a given file to the client with the
Content-Type taken from the files extension.
* `Stream`: Streams data to the client from an arbitrary `Read` value.
* Many Primitive Types: `String`, `&str`, `File`, `Option`, `Result`, and
others all implement the `Responder` trait.
'''