mirror of https://github.com/rwf2/Rocket.git
Update docs, examples and tests
This commit is contained in:
parent
872595b8fa
commit
6b9fb1aa97
|
@ -1361,13 +1361,13 @@ pub fn catchers(input: TokenStream) -> TokenStream {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// #[get("/person/<name>")]
|
/// // #[get("/person/<name>")]
|
||||||
/// fn maybe(name: Option<&str>) { }
|
/// // fn maybe(name: Option<&str>) { }
|
||||||
///
|
///
|
||||||
/// let bob1 = uri!(maybe(name = "Bob"));
|
/// // let bob1 = uri!(maybe(name = "Bob"));
|
||||||
/// let bob2 = uri!(maybe("Bob Smith"));
|
/// // let bob2 = uri!(maybe("Bob Smith"));
|
||||||
/// assert_eq!(bob1.to_string(), "/person/Bob");
|
/// // assert_eq!(bob1.to_string(), "/person/Bob");
|
||||||
/// assert_eq!(bob2.to_string(), "/person/Bob%20Smith");
|
/// // assert_eq!(bob2.to_string(), "/person/Bob%20Smith");
|
||||||
///
|
///
|
||||||
/// #[get("/person/<age>")]
|
/// #[get("/person/<age>")]
|
||||||
/// fn ok(age: Result<u8, std::num::ParseIntError>) { }
|
/// fn ok(age: Result<u8, std::num::ParseIntError>) { }
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
|
||||||
|
use std::num::ParseIntError;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use rocket::error::Empty;
|
||||||
use rocket::http::CookieJar;
|
use rocket::http::CookieJar;
|
||||||
use rocket::http::uri::fmt::{FromUriParam, Query};
|
use rocket::http::uri::fmt::{FromUriParam, Query};
|
||||||
use rocket::form::{Form, error::{Errors, ErrorKind}};
|
use rocket::form::{Form, error::{Errors, ErrorKind}};
|
||||||
|
@ -474,8 +476,8 @@ struct Third<'r> {
|
||||||
|
|
||||||
#[post("/<foo>/<bar>?<q1>&<rest..>")]
|
#[post("/<foo>/<bar>?<q1>&<rest..>")]
|
||||||
fn optionals(
|
fn optionals(
|
||||||
foo: Option<usize>,
|
foo: Result<usize, ParseIntError>,
|
||||||
bar: Option<String>,
|
bar: Result<String, Empty>,
|
||||||
q1: Result<usize, Errors<'_>>,
|
q1: Result<usize, Errors<'_>>,
|
||||||
rest: Option<Third<'_>>
|
rest: Option<Third<'_>>
|
||||||
) { }
|
) { }
|
||||||
|
@ -547,6 +549,13 @@ fn test_optional_uri_parameters() {
|
||||||
q1 = _,
|
q1 = _,
|
||||||
rest = _,
|
rest = _,
|
||||||
)) => "/10/hi%20there",
|
)) => "/10/hi%20there",
|
||||||
|
|
||||||
|
// uri!(optionals(
|
||||||
|
// foo = 10,
|
||||||
|
// bar = Err(Empty),
|
||||||
|
// q1 = _,
|
||||||
|
// rest = _,
|
||||||
|
// )) => "/10/hi%20there",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,15 +128,11 @@ pub type Outcome<'r, T, E = <T as FromData<'r>>::Error>
|
||||||
///
|
///
|
||||||
/// * `Option<T>`
|
/// * `Option<T>`
|
||||||
///
|
///
|
||||||
/// Forwards to `T`'s `FromData` implementation, capturing the outcome.
|
/// Forwards to `T`'s `FromData` implementation if there is data, capturing the outcome.
|
||||||
|
/// If `T` returns an Error or Forward, the `Option` returns the same.
|
||||||
///
|
///
|
||||||
/// - **Fails:** Never.
|
/// - **None:** If the data stream is empty.
|
||||||
///
|
/// - **Some:** If `T` succeeds to parse the incoming data.
|
||||||
/// - **Succeeds:** Always. If `T`'s `FromData` implementation succeeds, the
|
|
||||||
/// parsed value is returned in `Some`. If its implementation forwards or
|
|
||||||
/// fails, `None` is returned.
|
|
||||||
///
|
|
||||||
/// - **Forwards:** Never.
|
|
||||||
///
|
///
|
||||||
/// * `Result<T, T::Error>`
|
/// * `Result<T, T::Error>`
|
||||||
///
|
///
|
||||||
|
@ -423,6 +419,6 @@ impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
|
||||||
Outcome::Success(None)
|
Outcome::Success(None)
|
||||||
} else {
|
} else {
|
||||||
T::from_data(req, data).await.map(Some)
|
T::from_data(req, data).await.map(Some)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ use crate::http::uncased::AsUncased;
|
||||||
/// |------------------------|-------------|-------------------|--------|--------|----------------------------------------------------|
|
/// |------------------------|-------------|-------------------|--------|--------|----------------------------------------------------|
|
||||||
/// | [`Strict<T>`] | **strict** | if `strict` `T` | if `T` | if `T` | `T: FromForm` |
|
/// | [`Strict<T>`] | **strict** | if `strict` `T` | if `T` | if `T` | `T: FromForm` |
|
||||||
/// | [`Lenient<T>`] | **lenient** | if `lenient` `T` | if `T` | if `T` | `T: FromForm` |
|
/// | [`Lenient<T>`] | **lenient** | if `lenient` `T` | if `T` | if `T` | `T: FromForm` |
|
||||||
/// | `Option<T>` | **strict** | `None` | if `T` | if `T` | Infallible, `T: FromForm` |
|
/// | `Option<T>` | **strict** | `None` | if `T` | if `T` | `T: FromForm` |
|
||||||
/// | [`Result<T>`] | _inherit_ | `T::finalize()` | if `T` | if `T` | Infallible, `T: FromForm` |
|
/// | [`Result<T>`] | _inherit_ | `T::finalize()` | if `T` | if `T` | Infallible, `T: FromForm` |
|
||||||
/// | `Vec<T>` | _inherit_ | `vec![]` | if `T` | if `T` | `T: FromForm` |
|
/// | `Vec<T>` | _inherit_ | `vec![]` | if `T` | if `T` | `T: FromForm` |
|
||||||
/// | [`HashMap<K, V>`] | _inherit_ | `HashMap::new()` | if `V` | if `V` | `K: FromForm + Eq + Hash`, `V: FromForm` |
|
/// | [`HashMap<K, V>`] | _inherit_ | `HashMap::new()` | if `V` | if `V` | `K: FromForm + Eq + Hash`, `V: FromForm` |
|
||||||
|
@ -151,6 +151,12 @@ use crate::http::uncased::AsUncased;
|
||||||
///
|
///
|
||||||
/// ## Additional Notes
|
/// ## Additional Notes
|
||||||
///
|
///
|
||||||
|
/// * **`Option<T>` where `T: FromForm`**
|
||||||
|
///
|
||||||
|
/// `Option` is no longer Infallible. It now checks (depending on the strictness)
|
||||||
|
/// for whether any values were passed in, and returns an error if any values were passed in,
|
||||||
|
/// and the inner `T` failed to parse.
|
||||||
|
///
|
||||||
/// * **`Vec<T>` where `T: FromForm`**
|
/// * **`Vec<T>` where `T: FromForm`**
|
||||||
///
|
///
|
||||||
/// Parses a sequence of `T`'s. A new `T` is created whenever the field
|
/// Parses a sequence of `T`'s. A new `T` is created whenever the field
|
||||||
|
@ -814,7 +820,7 @@ impl<'v, K, V> FromForm<'v> for BTreeMap<K, V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OptionFormCtx<'v, T: FromForm<'v>> {
|
pub struct OptionFormCtx<'v, T: FromForm<'v>> {
|
||||||
strict: bool,
|
strict: bool,
|
||||||
has_field: bool,
|
has_field: bool,
|
||||||
inner: T::Context,
|
inner: T::Context,
|
||||||
|
|
|
@ -105,18 +105,20 @@ fn defaults() {
|
||||||
&[] => Result<'_, bool> = Ok(false),
|
&[] => Result<'_, bool> = Ok(false),
|
||||||
&[] => Result<'_, Strict<bool>> = Err(error::ErrorKind::Missing.into()),
|
&[] => Result<'_, Strict<bool>> = Err(error::ErrorKind::Missing.into()),
|
||||||
|
|
||||||
&["=unknown"] => Option<bool> = None,
|
&[] => Option<Lenient<bool>> = None,
|
||||||
&["=unknown"] => Option<Strict<bool>> = None,
|
|
||||||
&["=unknown"] => Option<Lenient<bool>> = None,
|
|
||||||
|
|
||||||
&[] => Option<Lenient<bool>> = Some(false.into()),
|
|
||||||
&["=123"] => Option<time::Date> = None,
|
|
||||||
|
|
||||||
&["=no"] => Option<bool> = Some(false),
|
&["=no"] => Option<bool> = Some(false),
|
||||||
&["=yes"] => Option<bool> = Some(true),
|
&["=yes"] => Option<bool> = Some(true),
|
||||||
&["=yes"] => Option<Lenient<bool>> = Some(true.into()),
|
&["=yes"] => Option<Lenient<bool>> = Some(true.into()),
|
||||||
&["=yes"] => Option<Strict<bool>> = Some(true.into()),
|
&["=yes"] => Option<Strict<bool>> = Some(true.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_parses_fail! {
|
||||||
|
&["=unknown"] => Option<bool>,
|
||||||
|
&["=unknown"] => Option<Strict<bool>>,
|
||||||
|
&["=unknown"] => Option<Lenient<bool>>,
|
||||||
|
&["=123"] => Option<time::Date>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # use rocket::post;
|
//! # use rocket::post;
|
||||||
//! # type S = Option<String>;
|
//! # type S = Option<String>;
|
||||||
//! # type E = std::convert::Infallible;
|
//! # type E = std::io::Error;
|
||||||
//! #[post("/", data = "<my_val>")]
|
//! #[post("/", data = "<my_val>")]
|
||||||
//! fn hello(my_val: Result<S, E>) { /* ... */ }
|
//! fn hello(my_val: Result<S, E>) { /* ... */ }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
@ -46,16 +46,9 @@ use crate::http::uri::{Segments, error::PathError, fmt::Path};
|
||||||
///
|
///
|
||||||
/// Sometimes, a forward is not desired, and instead, we simply want to know
|
/// Sometimes, a forward is not desired, and instead, we simply want to know
|
||||||
/// that the dynamic path segment could not be parsed into some desired type
|
/// that the dynamic path segment could not be parsed into some desired type
|
||||||
/// `T`. In these cases, types of `Option<T>`, `Result<T, T::Error>`, or
|
/// `T`. In these cases, types of `Result<T, T::Error>`, or
|
||||||
/// `Either<A, B>` can be used, which implement `FromParam` themselves.
|
/// `Either<A, B>` can be used, which implement `FromParam` themselves.
|
||||||
///
|
///
|
||||||
/// * **`Option<T>`** _where_ **`T: FromParam`**
|
|
||||||
///
|
|
||||||
/// Always returns successfully.
|
|
||||||
///
|
|
||||||
/// If the conversion to `T` fails, `None` is returned. If the conversion
|
|
||||||
/// succeeds, `Some(value)` is returned.
|
|
||||||
///
|
|
||||||
/// * **`Result<T, T::Error>`** _where_ **`T: FromParam`**
|
/// * **`Result<T, T::Error>`** _where_ **`T: FromParam`**
|
||||||
///
|
///
|
||||||
/// Always returns successfully.
|
/// Always returns successfully.
|
||||||
|
@ -121,14 +114,6 @@ use crate::http::uri::{Segments, error::PathError, fmt::Path};
|
||||||
/// Returns the percent-decoded path segment with invalid UTF-8 byte
|
/// Returns the percent-decoded path segment with invalid UTF-8 byte
|
||||||
/// sequences replaced by <20> U+FFFD.
|
/// sequences replaced by <20> U+FFFD.
|
||||||
///
|
///
|
||||||
/// * **Option<T>** _where_ **T: FromParam**
|
|
||||||
///
|
|
||||||
/// _This implementation always returns successfully._
|
|
||||||
///
|
|
||||||
/// The path segment is parsed by `T`'s `FromParam` implementation. If the
|
|
||||||
/// parse succeeds, a `Some(parsed_value)` is returned. Otherwise, a `None`
|
|
||||||
/// is returned.
|
|
||||||
///
|
|
||||||
/// * **Result<T, T::Error>** _where_ **T: FromParam**
|
/// * **Result<T, T::Error>** _where_ **T: FromParam**
|
||||||
///
|
///
|
||||||
/// _This implementation always returns successfully._
|
/// _This implementation always returns successfully._
|
||||||
|
@ -329,6 +314,11 @@ impl<'a, T: FromParam<'a>> FromParam<'a> for Result<T, T::Error> {
|
||||||
/// any other segments that begin with "*" or "." are ignored. If a
|
/// any other segments that begin with "*" or "." are ignored. If a
|
||||||
/// percent-decoded segment results in invalid UTF8, an `Err` is returned with
|
/// percent-decoded segment results in invalid UTF8, an `Err` is returned with
|
||||||
/// the `Utf8Error`.
|
/// the `Utf8Error`.
|
||||||
|
///
|
||||||
|
/// **`Option<T>` where `T: FromSegments`**
|
||||||
|
///
|
||||||
|
/// Succeeds as `None` if the this segments matched nothing, otherwise invokes
|
||||||
|
/// `T`'s `FromSegments` implementation.
|
||||||
pub trait FromSegments<'r>: Sized {
|
pub trait FromSegments<'r>: Sized {
|
||||||
/// The associated error to be returned when parsing fails.
|
/// The associated error to be returned when parsing fails.
|
||||||
type Error: std::fmt::Debug;
|
type Error: std::fmt::Debug;
|
||||||
|
|
|
@ -84,8 +84,7 @@ pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
|
||||||
/// If the `Outcome` is [`Error`], the request will fail with the given
|
/// If the `Outcome` is [`Error`], the request will fail with the given
|
||||||
/// status code and error. The designated error [`Catcher`](crate::Catcher)
|
/// status code and error. The designated error [`Catcher`](crate::Catcher)
|
||||||
/// will be used to respond to the request. Note that users can request types
|
/// will be used to respond to the request. Note that users can request types
|
||||||
/// of `Result<S, E>` and `Option<S>` to catch `Error`s and retrieve the
|
/// of `Result<S, E>` to catch `Error`s and retrieve the error value.
|
||||||
/// error value.
|
|
||||||
///
|
///
|
||||||
/// * **Forward**(Status)
|
/// * **Forward**(Status)
|
||||||
///
|
///
|
||||||
|
@ -177,9 +176,9 @@ pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
|
||||||
///
|
///
|
||||||
/// The type `T` is derived from the incoming request using `T`'s
|
/// The type `T` is derived from the incoming request using `T`'s
|
||||||
/// `FromRequest` implementation. If the derivation is a `Success`, the
|
/// `FromRequest` implementation. If the derivation is a `Success`, the
|
||||||
/// derived value is returned in `Some`. Otherwise, a `None` is returned.
|
/// derived value is returned in `Some`. If the derivation is a `Forward`,
|
||||||
///
|
/// the result is `None`, and if the derivation is an `Error`, the `Error`
|
||||||
/// _This implementation always returns successfully._
|
/// is preserved.
|
||||||
///
|
///
|
||||||
/// * **Result<T, T::Error>** _where_ **T: FromRequest**
|
/// * **Result<T, T::Error>** _where_ **T: FromRequest**
|
||||||
///
|
///
|
||||||
|
@ -189,6 +188,14 @@ pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
|
||||||
/// returned in `Err`. If the derivation is a `Forward`, the request is
|
/// returned in `Err`. If the derivation is a `Forward`, the request is
|
||||||
/// forwarded with the same status code as the original forward.
|
/// forwarded with the same status code as the original forward.
|
||||||
///
|
///
|
||||||
|
/// * **Outcome<T, T::Error>** _where_ **T: FromRequest**
|
||||||
|
///
|
||||||
|
/// The type `T` is derived from the incoming request using `T`'s
|
||||||
|
/// `FromRequest` implementation. The `Outcome` is then provided to the handler,
|
||||||
|
/// reguardless of what it returned.
|
||||||
|
///
|
||||||
|
/// _This guard **always** succeeds_
|
||||||
|
///
|
||||||
/// [`Config`]: crate::config::Config
|
/// [`Config`]: crate::config::Config
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -521,12 +528,13 @@ impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {
|
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {
|
||||||
type Error = Infallible;
|
type Error = T::Error;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
||||||
match T::from_request(request).await {
|
match T::from_request(request).await {
|
||||||
Success(val) => Success(Some(val)),
|
Success(val) => Success(Some(val)),
|
||||||
Error(_) | Forward(_) => Success(None),
|
Forward(_) => Success(None),
|
||||||
|
Error(e) => Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ fn set() -> Flash<&'static str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/unused")]
|
#[get("/unused")]
|
||||||
fn unused(flash: Option<FlashMessage<'_>>) -> Option<()> {
|
fn unused(flash: Result<FlashMessage<'_>, ()>) -> Option<()> {
|
||||||
flash.map(|_| ())
|
flash.ok().map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/use")]
|
#[get("/use")]
|
||||||
fn used(flash: Option<FlashMessage<'_>>) -> Option<String> {
|
fn used(flash: Result<FlashMessage<'_>, ()>) -> Option<String> {
|
||||||
flash.map(|f| f.message().into())
|
flash.ok().map(|f| f.message().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
mod flash_lazy_remove_tests {
|
mod flash_lazy_remove_tests {
|
||||||
|
|
|
@ -270,7 +270,7 @@ will be routed as follows:
|
||||||
You'll also find a route's rank logged in brackets during application launch:
|
You'll also find a route's rank logged in brackets during application launch:
|
||||||
`GET /user/<id> [3] (user_str)`.
|
`GET /user/<id> [3] (user_str)`.
|
||||||
|
|
||||||
Forwards can be _caught_ by using a `Result` or `Option` type. For example, if
|
Forwards can be _caught_ by using a `Option` type. For example, if
|
||||||
the type of `id` in the `user` function was `Result<usize, &str>`, then `user`
|
the type of `id` in the `user` function was `Result<usize, &str>`, then `user`
|
||||||
would never forward. An `Ok` variant would indicate that `<id>` was a valid
|
would never forward. An `Ok` variant would indicate that `<id>` was a valid
|
||||||
`usize`, while an `Err` would indicate that `<id>` was not a `usize`. The
|
`usize`, while an `Err` would indicate that `<id>` was not a `usize`. The
|
||||||
|
@ -279,7 +279,7 @@ would never forward. An `Ok` variant would indicate that `<id>` was a valid
|
||||||
! tip: It's not just forwards that can be caught!
|
! tip: It's not just forwards that can be caught!
|
||||||
|
|
||||||
In general, when any guard fails for any reason, including parameter guards,
|
In general, when any guard fails for any reason, including parameter guards,
|
||||||
you can use an `Option` or `Result` type in its place to catch the error.
|
you can use a `Result` type in its place to catch the error.
|
||||||
|
|
||||||
By the way, if you were to omit the `rank` parameter in the `user_str` or
|
By the way, if you were to omit the `rank` parameter in the `user_str` or
|
||||||
`user_int` routes, Rocket would emit an error and abort launch, indicating that
|
`user_int` routes, Rocket would emit an error and abort launch, indicating that
|
||||||
|
@ -511,8 +511,7 @@ it always succeeds. The user is redirected to a log in page.
|
||||||
### Fallible Guards
|
### Fallible Guards
|
||||||
|
|
||||||
A failing or forwarding guard can be "caught" in handler, preventing it from
|
A failing or forwarding guard can be "caught" in handler, preventing it from
|
||||||
failing or forwarding, via the `Option<T>` and `Result<T, E>` guards. When a
|
failing or forwarding, via `Result<T, E>` guards. If a guard `T` fails
|
||||||
guard `T` fails or forwards, `Option<T>` will be `None`. If a guard `T` fails
|
|
||||||
with error `E`, `Result<T, E>` will be `Err(E)`.
|
with error `E`, `Result<T, E>` will be `Err(E)`.
|
||||||
|
|
||||||
As an example, for the `User` guard above, instead of allowing the guard to
|
As an example, for the `User` guard above, instead of allowing the guard to
|
||||||
|
@ -538,7 +537,7 @@ fn admin_panel_user(user: Option<User>) -> Result<&'static str, Redirect> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If the `User` guard forwards or fails, the `Option` will be `None`. If it
|
If the `User` guard forwards, the `Option` will be `None`. If it
|
||||||
succeeds, it will be `Some(User)`.
|
succeeds, it will be `Some(User)`.
|
||||||
|
|
||||||
For guards that may fail (and not just forward), the `Result<T, E>` guard allows
|
For guards that may fail (and not just forward), the `Result<T, E>` guard allows
|
||||||
|
@ -898,14 +897,14 @@ If a `POST /todo` request arrives, the form data will automatically be parsed
|
||||||
into the `Task` structure. If the data that arrives isn't of the correct
|
into the `Task` structure. If the data that arrives isn't of the correct
|
||||||
Content-Type, the request is forwarded. If the data doesn't parse or is simply
|
Content-Type, the request is forwarded. If the data doesn't parse or is simply
|
||||||
invalid, a customizable error is returned. As before, a forward or error can
|
invalid, a customizable error is returned. As before, a forward or error can
|
||||||
be caught by using the `Option` and `Result` types:
|
be caught by using the `Result` types:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# use rocket::{post, form::Form};
|
# use rocket::{post, form::{Form, Errors}};
|
||||||
# type Task<'r> = &'r str;
|
# type Task<'r> = &'r str;
|
||||||
|
|
||||||
#[post("/todo", data = "<task>")]
|
#[post("/todo", data = "<task>")]
|
||||||
fn new(task: Option<Form<Task<'_>>>) { /* .. */ }
|
fn new(task: Result<Form<Task<'_>>, Errors<'_>>) { /* .. */ }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multipart
|
### Multipart
|
||||||
|
|
|
@ -616,18 +616,20 @@ For example, given the following route:
|
||||||
```rust
|
```rust
|
||||||
# #[macro_use] extern crate rocket;
|
# #[macro_use] extern crate rocket;
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
|
# use std::num::ParseIntError;
|
||||||
|
|
||||||
#[get("/<id>/<name>?<age>")]
|
#[get("/<id>/<name>?<age>")]
|
||||||
fn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }
|
fn person(id: Result<usize, ParseIntError>, name: &str, age: Option<u8>) { /* .. */ }
|
||||||
```
|
```
|
||||||
|
|
||||||
URIs to `person` can be created as follows:
|
URIs to `person` can be created as follows:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #[macro_use] extern crate rocket;
|
# #[macro_use] extern crate rocket;
|
||||||
|
# use std::num::ParseIntError;
|
||||||
|
|
||||||
# #[get("/<id>/<name>?<age>")]
|
# #[get("/<id>/<name>?<age>")]
|
||||||
# fn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }
|
# fn person(id: Result<usize, ParseIntError>, name: &str, age: Option<u8>) { /* .. */ }
|
||||||
|
|
||||||
// with unnamed parameters, in route path declaration order
|
// with unnamed parameters, in route path declaration order
|
||||||
let mike = uri!(person(101, "Mike Smith", Some(28)));
|
let mike = uri!(person(101, "Mike Smith", Some(28)));
|
||||||
|
@ -755,9 +757,10 @@ generated.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #[macro_use] extern crate rocket;
|
# #[macro_use] extern crate rocket;
|
||||||
|
# use std::num::ParseIntError;
|
||||||
|
|
||||||
#[get("/<id>/<name>?<age>")]
|
#[get("/<id>/<name>?<age>")]
|
||||||
fn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }
|
fn person(id: Result<usize, ParseIntError>, name: &str, age: Option<u8>) { /* .. */ }
|
||||||
|
|
||||||
// Note that `id` is `Option<usize>` in the route, but `id` in `uri!` _cannot_
|
// Note that `id` is `Option<usize>` in the route, but `id` in `uri!` _cannot_
|
||||||
// be an `Option`. `age`, on the other hand, _must_ be an `Option` (or `Result`
|
// be an `Option`. `age`, on the other hand, _must_ be an `Option` (or `Result`
|
||||||
|
|
|
@ -53,8 +53,8 @@ fn login(_user: User) -> Redirect {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/login", rank = 2)]
|
#[get("/login", rank = 2)]
|
||||||
fn login_page(flash: Option<FlashMessage<'_>>) -> Template {
|
fn login_page(flash: Result<FlashMessage<'_>, ()>) -> Template {
|
||||||
Template::render("login", flash)
|
Template::render("login", flash.ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/login", data = "<login>")]
|
#[post("/login", data = "<login>")]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
|
||||||
|
use rocket::form::Errors;
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
#[derive(FromFormField)]
|
#[derive(FromFormField)]
|
||||||
|
@ -51,13 +53,13 @@ fn wave(name: &str, age: u8) -> String {
|
||||||
// http://127.0.0.1:8000/?name=Rocketeer&lang=en&emoji
|
// http://127.0.0.1:8000/?name=Rocketeer&lang=en&emoji
|
||||||
// http://127.0.0.1:8000/?lang=ru&emoji&name=Rocketeer
|
// http://127.0.0.1:8000/?lang=ru&emoji&name=Rocketeer
|
||||||
#[get("/?<lang>&<opt..>")]
|
#[get("/?<lang>&<opt..>")]
|
||||||
fn hello(lang: Option<Lang>, opt: Options<'_>) -> String {
|
fn hello(lang: Result<Lang, Errors<'_>>, opt: Options<'_>) -> String {
|
||||||
let mut greeting = String::new();
|
let mut greeting = String::new();
|
||||||
if opt.emoji {
|
if opt.emoji {
|
||||||
greeting.push_str("👋 ");
|
greeting.push_str("👋 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
match lang {
|
match lang.ok() {
|
||||||
Some(Lang::Russian) => greeting.push_str("Привет"),
|
Some(Lang::Russian) => greeting.push_str("Привет"),
|
||||||
Some(Lang::English) => greeting.push_str("Hello"),
|
Some(Lang::English) => greeting.push_str("Hello"),
|
||||||
None => greeting.push_str("Hi"),
|
None => greeting.push_str("Hi"),
|
||||||
|
|
|
@ -86,8 +86,8 @@ async fn delete(id: i32, conn: DbConn) -> Result<Flash<Redirect>, Template> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(flash: Option<FlashMessage<'_>>, conn: DbConn) -> Template {
|
async fn index(flash: Result<FlashMessage<'_>, ()>, conn: DbConn) -> Template {
|
||||||
let flash = flash.map(FlashMessage::into_inner);
|
let flash = flash.ok().map(FlashMessage::into_inner);
|
||||||
Template::render("index", Context::raw(&conn, flash).await)
|
Template::render("index", Context::raw(&conn, flash).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue