mirror of https://github.com/rwf2/Rocket.git
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:
parent
5ee9fbd20b
commit
c99ed8b7c6
|
@ -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)
|
* 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)
|
* 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).
|
||||||
|
|
|
@ -619,56 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
|
||||||
copy of the Program in return for a fee.
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
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>.
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Rocket is a web framework for Rust. If you'd like, you can think of Rocket as
|
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),
|
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
|
[Bottle](http://bottlepy.org/docs/dev/index.html), and
|
||||||
[Yesod](http://www.yesodweb.com/). We prefer to think of Rocket as something
|
[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
|
new. Rocket aims to be fast, easy, and flexible. It also aims to be _fun_, and
|
|
@ -3,7 +3,7 @@
|
||||||
Before you can start writing a Rocket application, you'll need a **nightly**
|
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
|
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
|
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.
|
section.
|
||||||
|
|
||||||
## Running Examples
|
## Running Examples
|
||||||
|
@ -15,7 +15,7 @@ For instance, the following set of commands runs the `hello_world` example:
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/SergioBenitez/Rocket
|
git clone https://github.com/SergioBenitez/Rocket
|
||||||
cd Rocket
|
cd Rocket
|
||||||
git checkout v0.3.17
|
git checkout v0.3
|
||||||
cd examples/hello_world
|
cd examples/hello_world
|
||||||
cargo run
|
cargo run
|
||||||
```
|
```
|
|
@ -71,7 +71,7 @@ fn world() -> &'static str { // <- request handler
|
||||||
This declares the `world` route to match against the static path `"/world"` on
|
This declares the `world` route to match against the static path `"/world"` on
|
||||||
incoming `GET` requests. The `world` route is simple, but additional route
|
incoming `GET` requests. The `world` route is simple, but additional route
|
||||||
parameters are necessary when building more interesting applications. The
|
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.
|
constructing routes.
|
||||||
|
|
||||||
## Mounting
|
## Mounting
|
||||||
|
@ -179,7 +179,7 @@ we expected.
|
||||||
|
|
||||||
A version of this example's complete crate, ready to `cargo run`, can be found
|
A version of this example's complete crate, ready to `cargo run`, can be found
|
||||||
on
|
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
|
You can find dozens of other complete examples, spanning all of Rocket's
|
||||||
features, in the [GitHub examples
|
features, in the [GitHub examples
|
||||||
directory](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/).
|
directory](@git/v0.3/examples/).
|
|
@ -38,7 +38,7 @@ to the root path:
|
||||||
```
|
```
|
||||||
|
|
||||||
The grammar for these attributes is defined formally in the
|
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
|
### 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
|
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.
|
`"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
|
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.
|
makes use of this feature to submit `PUT` and `DELETE` requests from a web form.
|
||||||
|
|
||||||
## Dynamic Segments
|
## 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/v0.3/rocket/request/trait.FromParam.html
|
||||||
[`FromParam` API docs]: https://api.rocket.rs/rocket/request/trait.FromParam.html
|
[`FromParam` API docs]: @api/v0.3/rocket/request/trait.FromParam.html
|
||||||
|
|
||||||
### Raw Strings
|
### 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
|
you want direct but potentially unsafe access to the string (`&RawStr`), or safe
|
||||||
access to the string at the cost of an allocation (`String`).
|
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
|
## 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
|
## 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`]
|
more about request guards and implementing them, see the [`FromRequest`]
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
[`FromRequest`]: https://api.rocket.rs/rocket/request/trait.FromRequest.html
|
[`FromRequest`]: @api/v0.3/rocket/request/trait.FromRequest.html
|
||||||
[`Cookies`]: https://api.rocket.rs/rocket/http/enum.Cookies.html
|
[`Cookies`]: @api/v0.3/rocket/http/enum.Cookies.html
|
||||||
|
|
||||||
### Custom Guards
|
### 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
|
illustrates further use of the `Cookies` type to get and set cookies, while the
|
||||||
[`Cookies`] documentation contains complete usage information.
|
[`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
|
### 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
|
### 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`.
|
can be generated with the command `openssl rand -base64 32`.
|
||||||
|
|
||||||
For more information on configuration, see the
|
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
|
[`get_private`]: @api/v0.3/rocket/http/enum.Cookies.html#method.get_private
|
||||||
[`add_private`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.add_private
|
[`add_private`]: @api/v0.3/rocket/http/enum.Cookies.html#method.add_private
|
||||||
[`remove_private`]: https://api.rocket.rs/rocket/http/enum.Cookies.html#method.remove_private
|
[`remove_private`]: @api/v0.3/rocket/http/enum.Cookies.html#method.remove_private
|
||||||
|
|
||||||
### One-At-A-Time
|
### One-At-A-Time
|
||||||
|
|
||||||
|
@ -489,7 +489,7 @@ fn new(input: T) -> String { ... }
|
||||||
|
|
||||||
Any type that implements [`FromData`] is also known as _data guard_.
|
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
|
### 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 { ... }
|
fn new(task: Option<Form<Task>>) -> String { ... }
|
||||||
```
|
```
|
||||||
|
|
||||||
[`FromForm`]: https://api.rocket.rs/rocket/request/trait.FromForm.html
|
[`FromForm`]: @api/v0.3/rocket/request/trait.FromForm.html
|
||||||
[`FromFormValue`]: https://api.rocket.rs/rocket/request/trait.FromFormValue.html
|
[`FromFormValue`]: @api/v0.3/rocket/request/trait.FromFormValue.html
|
||||||
|
|
||||||
#### Lenient Parsing
|
#### Lenient Parsing
|
||||||
|
|
||||||
|
@ -556,7 +556,7 @@ struct Task { .. }
|
||||||
fn new(task: LenientForm<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
|
#### Field Renaming
|
||||||
|
|
||||||
|
@ -621,14 +621,14 @@ struct Person {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The [forms validation](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/form_validation)
|
The [forms validation](@git/v0.3/examples/form_validation)
|
||||||
and [forms kitchen sink](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/form_kitchen_sink)
|
and [forms kitchen sink](@git/v0.3/examples/form_kitchen_sink)
|
||||||
examples on GitHub provide further illustrations.
|
examples on GitHub provide further illustrations.
|
||||||
|
|
||||||
### JSON
|
### JSON
|
||||||
|
|
||||||
Handling JSON data is no harder: simply use the
|
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
|
```rust
|
||||||
#[derive(Deserialize)]
|
#[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
|
`Deserialize` trait from [Serde](https://github.com/serde-rs/json). See the
|
||||||
[JSON example] on GitHub for a complete example.
|
[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
|
### Streaming
|
||||||
|
|
||||||
Sometimes you just want to handle incoming data directly. For example, you might
|
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
|
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:
|
type:
|
||||||
|
|
||||||
```rust
|
```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
|
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
|
returned. The handler above is complete. It really is that simple! See the
|
||||||
[GitHub example
|
[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.
|
for the full crate.
|
||||||
|
|
||||||
## Query Strings
|
## Query Strings
|
||||||
|
@ -723,14 +723,14 @@ fn new(task: Option<Task>) { ... }
|
||||||
|
|
||||||
For a concrete illustration on how to handle query parameters, see [the
|
For a concrete illustration on how to handle query parameters, see [the
|
||||||
`query_params`
|
`query_params`
|
||||||
example](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/query_params).
|
example](@git/v0.3/examples/query_params).
|
||||||
|
|
||||||
## Error Catchers
|
## Error Catchers
|
||||||
|
|
||||||
Routing may fail for a variety of reasons. These include:
|
Routing may fail for a variety of reasons. These include:
|
||||||
|
|
||||||
* A [request guard](#request-guards) returns `Failure`.
|
* 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.
|
* No matching route was found.
|
||||||
|
|
||||||
If any of these conditions occur, Rocket returns an error to the client. To do
|
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
|
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
|
types [`Request`](@api/v0.3/rocket/struct.Request.html) and/or
|
||||||
[`Error`](https://api.rocket.rs/rocket/enum.Error.html). At present, the `Error`
|
[`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
|
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.
|
GitHub illustrates their use in full.
|
||||||
|
|
||||||
Rocket has a default catcher for all of the standard HTTP error codes including
|
Rocket has a default catcher for all of the standard HTTP error codes including
|
|
@ -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.
|
`Responder` trait as well as several useful `Responder`s provided by Rocket.
|
||||||
We'll also briefly discuss how to implement your own `Responder`.
|
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
|
## 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
|
`File` uses a streamed response. Responders may dynamically adjust their
|
||||||
responses according to the incoming `Request` they are responding to.
|
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
|
### Wrapping
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ struct WrappingResponder<R>(R);
|
||||||
|
|
||||||
A wrapping responder modifies the response returned by `R` before responding
|
A wrapping responder modifies the response returned by `R` before responding
|
||||||
with that same response. For instance, Rocket provides `Responder`s in the
|
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
|
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
|
[`Accepted`] type sets the status to `202 - Accepted`. It can be used as
|
||||||
follows:
|
follows:
|
||||||
|
@ -46,7 +46,7 @@ fn new(id: usize) -> status::Accepted<String> {
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly, the types in the [`content`
|
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
|
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:
|
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
|
[`Accepted`]: @api/v0.3/rocket/response/status/struct.Accepted.html
|
||||||
[`content::Json`]: https://api.rocket.rs/rocket/response/content/struct.Json.html
|
[`content::Json`]: @api/v0.3/rocket/response/content/struct.Json.html
|
||||||
|
|
||||||
### Errors
|
### Errors
|
||||||
|
|
||||||
Responders may fail; they need not _always_ generate a response. Instead, they
|
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
|
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.
|
given status code.
|
||||||
|
|
||||||
If an error catcher has been registered for the given status code, Rocket will
|
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.
|
response.
|
||||||
|
|
||||||
While not encouraged, you can also forward a request to a catcher manually by
|
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
|
type. For instance, to forward to the catcher for **406 - Not Acceptable**, you
|
||||||
would write:
|
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.
|
* [`status`] - Contains types that override the status code of a response.
|
||||||
* [`Flash`] - Sets a "flash" cookie that is removed when accessed.
|
* [`Flash`] - Sets a "flash" cookie that is removed when accessed.
|
||||||
|
|
||||||
[`status`]: https://api.rocket.rs/rocket/response/status/index.html
|
[`status`]: @api/v0.3/rocket/response/status/index.html
|
||||||
[`response`]: https://api.rocket.rs/rocket/response/index.html
|
[`response`]: @api/v0.3/rocket/response/index.html
|
||||||
[`NamedFile`]: https://api.rocket.rs/rocket/response/struct.NamedFile.html
|
[`NamedFile`]: @api/v0.3/rocket/response/struct.NamedFile.html
|
||||||
[`Content`]: https://api.rocket.rs/rocket/response/struct.Content.html
|
[`Content`]: @api/v0.3/rocket/response/struct.Content.html
|
||||||
[`Redirect`]: https://api.rocket.rs/rocket/response/struct.Redirect.html
|
[`Redirect`]: @api/v0.3/rocket/response/struct.Redirect.html
|
||||||
[`Stream`]: https://api.rocket.rs/rocket/response/struct.Stream.html
|
[`Stream`]: @api/v0.3/rocket/response/struct.Stream.html
|
||||||
[`Flash`]: https://api.rocket.rs/rocket/response/struct.Flash.html
|
[`Flash`]: @api/v0.3/rocket/response/struct.Flash.html
|
||||||
|
|
||||||
### Streaming
|
### 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
|
### JSON
|
||||||
|
|
||||||
|
@ -233,10 +233,10 @@ fails, a **500 - Internal Server Error** is returned.
|
||||||
|
|
||||||
The [JSON example on GitHub] provides further illustration.
|
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
|
[`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html
|
||||||
[`serde`]: https://docs.serde.rs/serde/
|
[`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
|
### 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.
|
with `.tera`, Tera is used.
|
||||||
|
|
||||||
For templates to be properly registered, the template fairing must be attached
|
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
|
provides more information on fairings. To attach the template fairing, simply
|
||||||
call `.attach(Template::fairing())` on an instance of `Rocket` as follows:
|
call `.attach(Template::fairing())` on an instance of `Rocket` as follows:
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ fn main() {
|
||||||
The [`Template`] API
|
The [`Template`] API
|
||||||
documentation contains more information about templates, while the [Handlebars
|
documentation contains more information about templates, while the [Handlebars
|
||||||
Templates example on
|
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.
|
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
|
|
@ -22,7 +22,7 @@ The process for using managed state is simple:
|
||||||
### Adding State
|
### Adding State
|
||||||
|
|
||||||
To instruct Rocket to manage state for your application, call the
|
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`
|
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
|
structure with an internal `AtomicUsize` with an initial value of `0`, we can
|
||||||
write the following:
|
write the following:
|
||||||
|
@ -48,8 +48,8 @@ rocket::ignite()
|
||||||
### Retrieving State
|
### Retrieving State
|
||||||
|
|
||||||
State that is being managed by Rocket can be retrieved via the
|
State that is being managed by Rocket can be retrieved via the
|
||||||
[`State`](https://api.rocket.rs/rocket/struct.State.html) type: a [request
|
[`State`](@api/v0.3/rocket/struct.State.html) type: a [request
|
||||||
guard](/guide/requests/#request-guards) for managed state. To use the 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
|
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
|
the managed state. For example, we can retrieve and respond with the current
|
||||||
`HitCount` in a `count` route as follows:
|
`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
|
### 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
|
You can find a complete example using the `HitCount` structure in the [state
|
||||||
example on
|
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`
|
learn more about the [`manage`
|
||||||
method](https://api.rocket.rs/rocket/struct.Rocket.html#method.manage) and
|
method](@api/v0.3/rocket/struct.Rocket.html#method.manage) and
|
||||||
[`State` type](https://api.rocket.rs/rocket/struct.State.html) in the API docs.
|
[`State` type](@api/v0.3/rocket/struct.State.html) in the API docs.
|
||||||
|
|
||||||
## Databases
|
## Databases
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ fn handler(conn: DbConn) { ... }
|
||||||
|
|
||||||
To get started, we need to depend on the `diesel` and `r2d2` crates. For
|
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
|
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:
|
use the following dependencies:
|
||||||
|
|
||||||
```
|
```
|
|
@ -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
|
application. On the other hand, you _should_ use a fairing to record timing and
|
||||||
usage statistics or to enforce global security policies.
|
usage statistics or to enforce global security policies.
|
||||||
|
|
||||||
[`Fairing`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html
|
[`Fairing`]: @api/v0.3/rocket/fairing/trait.Fairing.html
|
||||||
[request guard]: /guide/requests/#request-guards
|
[request guard]: ../requests/#request-guards
|
||||||
[request guards]: /guide/requests/#request-guards
|
[request guards]: ../requests/#request-guards
|
||||||
[data guards]: /guide/requests/#body-data
|
[data guards]: ../requests/#body-data
|
||||||
|
|
||||||
### Attaching
|
### Attaching
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ rocket::ignite()
|
||||||
.launch();
|
.launch();
|
||||||
```
|
```
|
||||||
|
|
||||||
[`attach`]: https://api.rocket.rs/rocket/struct.Rocket.html#method.attach
|
[`attach`]: @api/v0.3/rocket/struct.Rocket.html#method.attach
|
||||||
[`Rocket`]: https://api.rocket.rs/rocket/struct.Rocket.html
|
[`Rocket`]: @api/v0.3/rocket/struct.Rocket.html
|
||||||
|
|
||||||
Fairings are executed in the order in which they are attached: the first
|
Fairings are executed in the order in which they are attached: the first
|
||||||
attached fairing has its callbacks executed before all others. Because fairing
|
attached fairing has its callbacks executed before all others. Because fairing
|
||||||
|
@ -68,7 +68,7 @@ events is described below:
|
||||||
* **Attach (`on_attach`)**
|
* **Attach (`on_attach`)**
|
||||||
|
|
||||||
An attach callback is called when a fairing is first attached via the
|
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
|
method. An attach callback can arbitrarily modify the `Rocket` instance
|
||||||
being constructed and optionally abort launch. Attach fairings are commonly
|
being constructed and optionally abort launch. Attach fairings are commonly
|
||||||
used to parse and validate configuration values, aborting on bad
|
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
|
[`on_launch`], [`on_request`], and [`on_response`]. Each callback has a default
|
||||||
implementation that does absolutely nothing.
|
implementation that does absolutely nothing.
|
||||||
|
|
||||||
[`Info`]: https://api.rocket.rs/rocket/fairing/struct.Info.html
|
[`Info`]: @api/v0.3/rocket/fairing/struct.Info.html
|
||||||
[`info`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#tymethod.info
|
[`info`]: @api/v0.3/rocket/fairing/trait.Fairing.html#tymethod.info
|
||||||
[`on_attach`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_attach
|
[`on_attach`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_attach
|
||||||
[`on_launch`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_launch
|
[`on_launch`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_launch
|
||||||
[`on_request`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_request
|
[`on_request`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_request
|
||||||
[`on_response`]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html#method.on_response
|
[`on_response`]: @api/v0.3/rocket/fairing/trait.Fairing.html#method.on_response
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ impl Fairing for Counter {
|
||||||
|
|
||||||
For brevity, imports are not shown. The complete example can be found in the
|
For brevity, imports are not shown. The complete example can be found in the
|
||||||
[`Fairing`
|
[`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
|
## 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
|
||||||
|
|
|
@ -36,10 +36,10 @@ instance. Usage is straightforward:
|
||||||
let response = req.dispatch();
|
let response = req.dispatch();
|
||||||
```
|
```
|
||||||
|
|
||||||
[`local`]: https://api.rocket.rs/rocket/local/index.html
|
[`local`]: @api/v0.3/rocket/local/index.html
|
||||||
[`Client`]: https://api.rocket.rs/rocket/local/struct.Client.html
|
[`Client`]: @api/v0.3/rocket/local/struct.Client.html
|
||||||
[`LocalRequest`]: https://api.rocket.rs/rocket/local/struct.LocalRequest.html
|
[`LocalRequest`]: @api/v0.3/rocket/local/struct.LocalRequest.html
|
||||||
[`Rocket`]: https://api.rocket.rs/rocket/struct.Rocket.html
|
[`Rocket`]: @api/v0.3/rocket/struct.Rocket.html
|
||||||
|
|
||||||
## Validating Responses
|
## Validating Responses
|
||||||
|
|
||||||
|
@ -57,13 +57,13 @@ a few below:
|
||||||
* [`body_string`]: returns the body data as a `String`.
|
* [`body_string`]: returns the body data as a `String`.
|
||||||
* [`body_bytes`]: returns the body data as a `Vec<u8>`.
|
* [`body_bytes`]: returns the body data as a `Vec<u8>`.
|
||||||
|
|
||||||
[`LocalResponse`]: https://api.rocket.rs/rocket/local/struct.LocalResponse.html
|
[`LocalResponse`]: @api/v0.3/rocket/local/struct.LocalResponse.html
|
||||||
[`Response`]: https://api.rocket.rs/rocket/struct.Response.html
|
[`Response`]: @api/v0.3/rocket/struct.Response.html
|
||||||
[`status`]: https://api.rocket.rs/rocket/struct.Response.html#method.status
|
[`status`]: @api/v0.3/rocket/struct.Response.html#method.status
|
||||||
[`content_type`]: https://api.rocket.rs/rocket/struct.Response.html#method.content_type
|
[`content_type`]: @api/v0.3/rocket/struct.Response.html#method.content_type
|
||||||
[`headers`]: https://api.rocket.rs/rocket/struct.Response.html#method.headers
|
[`headers`]: @api/v0.3/rocket/struct.Response.html#method.headers
|
||||||
[`body_string`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_string
|
[`body_string`]: @api/v0.3/rocket/struct.Response.html#method.body_string
|
||||||
[`body_bytes`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_bytes
|
[`body_bytes`]: @api/v0.3/rocket/struct.Response.html#method.body_bytes
|
||||||
|
|
||||||
These methods are typically used in combination with the `assert_eq!` or
|
These methods are typically used in combination with the `assert_eq!` or
|
||||||
`assert!` macros as follows:
|
`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
|
The tests can be run with `cargo test`. You can find the full source code to
|
||||||
[this example on
|
[this example on
|
||||||
GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.3.17/examples/testing).
|
GitHub](@git/v0.3/examples/testing).
|
||||||
|
|
||||||
## Codegen Debug
|
## Codegen Debug
|
||||||
|
|
|
@ -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
|
data limits as well. Data limits can be retrieved at runtime via the
|
||||||
[`Request::limits()`] method.
|
[`Request::limits()`] method.
|
||||||
|
|
||||||
[`Request::limits()`]: https://api.rocket.rs/rocket/struct.Request.html#method.limits
|
[`Request::limits()`]: @api/v0.3/rocket/struct.Request.html#method.limits
|
||||||
[`Json`]: https://api.rocket.rs/rocket_contrib/struct.Json.html#incoming-data-limits
|
[`Json`]: @api/v0.3/rocket_contrib/struct.Json.html#incoming-data-limits
|
||||||
|
|
||||||
## Extras
|
## 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
|
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
|
these parameters aren't used by Rocket directly, other libraries, or your own
|
||||||
application, can use them as they wish. As an example, the
|
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
|
accepts a value for the `template_dir` configuration parameter. The parameter
|
||||||
can be set in `Rocket.toml` as follows:
|
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].
|
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:
|
For example, if your application makes use of a custom `assets_dir` parameter:
|
||||||
|
|
||||||
[ad-hoc attach fairing]: /guide/fairings/#ad-hoc-fairings
|
[ad-hoc attach fairing]: ../fairings/#ad-hoc-fairings
|
||||||
[managed state]: /guide/state/#managed-state
|
[managed state]: ../state/#managed-state
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[development]
|
[development]
|
|
@ -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
|
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
|
can read more about how Rocket formulates responses at the [API documentation
|
||||||
for the Responder
|
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
|
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:
|
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;
|
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
|
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.
|
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
|
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 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`
|
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
|
as a **404** error, which is exactly what we want to return when the requested
|
||||||
paste doesn't exist.
|
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
|
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!
|
you off!
|
||||||
|
|
||||||
The issue is that the _user_ controls the value of `id`, and as a result, can
|
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
|
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
|
`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
|
implement the validation and ensure that the `id` is a valid `PasteID` before
|
||||||
using it. We do this by implementing `FromParam` for `PasteID` in
|
using it. We do this by implementing `FromParam` for `PasteID` in
|
||||||
`src/paste_id.rs`, as below:
|
`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
|
* 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
|
`<id>` for language `<lang>`. If `<lang>` is not a known language, do no
|
||||||
highlighting. Possibly validate `<lang>` with `FromParam`.
|
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.
|
unit tests for your pastebin.
|
||||||
* Dispatch a thread before `launch`ing Rocket in `main` that periodically
|
* Dispatch a thread before `launch`ing Rocket in `main` that periodically
|
||||||
cleans up idling old pastes in `upload/`.
|
cleans up idling old pastes in `upload/`.
|
||||||
|
|
||||||
You can find the full source code for the [completed pastebin tutorial on
|
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).
|
|
@ -22,7 +22,7 @@ guide.
|
||||||
|
|
||||||
The best way to learn Rocket is to _build something_. It should be fun and easy,
|
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
|
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
|
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!
|
decide to do next, we hope you have a blast!
|
|
@ -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
|
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
|
a reference for experienced Rocket developers. This guide is conversational in
|
||||||
tone. For concise and purely technical documentation, see the [API
|
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
|
The guide is split into several sections, each with a focus on a different
|
||||||
aspect of Rocket. The sections are:
|
aspect of Rocket. The sections are:
|
|
@ -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).
|
|
193
site/index.toml
193
site/index.toml
|
@ -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**, you’d
|
|
||||||
see:
|
|
||||||
|
|
||||||
<span class="callout">Hello, 58 year old named John!</span>
|
|
||||||
|
|
||||||
If someone visits a path with an `<age>` that isn’t a `u8`, Rocket doesn’t
|
|
||||||
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 doesn’t 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 Rocket’s `FromData` trait,
|
|
||||||
Rocket’s 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'
|
|
|
@ -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.
|
|
||||||
"""
|
|
|
@ -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).
|
|
|
@ -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!
|
|
|
@ -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 route’s
|
|
||||||
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
|
|
||||||
you’ll likely spend the most time writing. In Rocket, handlers are simply
|
|
||||||
functions - that’s it! The only caveat is that the function’s 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 type’s 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 file’s 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.
|
|
||||||
'''
|
|
Loading…
Reference in New Issue