mirror of https://github.com/rwf2/Rocket.git
Rename 'Outcome::Failure' to 'Outcome::Error'.
The primary motivation is to deconflate the leading `F`s in `Failure` and `Forward`. In particular, when using a generics, we used `F` for forward, which could easily be confused for `F` for `Failure`. This resolves the conflation.
This commit is contained in:
parent
55b7d4574a
commit
b6430e9970
|
@ -67,7 +67,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream {
|
||||||
) -> rocket::request::Outcome<Self, Self::Error> {
|
) -> rocket::request::Outcome<Self, Self::Error> {
|
||||||
match #db_ty::fetch(req.rocket()) {
|
match #db_ty::fetch(req.rocket()) {
|
||||||
Some(db) => rocket::outcome::Outcome::Success(db),
|
Some(db) => rocket::outcome::Outcome::Success(db),
|
||||||
None => rocket::outcome::Outcome::Failure((
|
None => rocket::outcome::Outcome::Error((
|
||||||
rocket::http::Status::InternalServerError, ()))
|
rocket::http::Status::InternalServerError, ()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ pub struct Initializer<D: Database>(Option<&'static str>, PhantomData<fn() -> D>
|
||||||
/// [`connect_timeout`](crate::Config::connect_timeout) seconds.
|
/// [`connect_timeout`](crate::Config::connect_timeout) seconds.
|
||||||
/// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with
|
/// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with
|
||||||
/// status `InternalServerError`. A [`Sentinel`] guards this condition, and so
|
/// status `InternalServerError`. A [`Sentinel`] guards this condition, and so
|
||||||
/// this type of failure is unlikely to occur. A `None` error is returned.
|
/// this type of error is unlikely to occur. A `None` error is returned.
|
||||||
/// * If a connection is not available within `connect_timeout` seconds or
|
/// * If a connection is not available within `connect_timeout` seconds or
|
||||||
/// another error occurs, the guard _fails_ with status `ServiceUnavailable`
|
/// another error occurs, the guard _fails_ with status `ServiceUnavailable`
|
||||||
/// and the error is returned in `Some`.
|
/// and the error is returned in `Some`.
|
||||||
|
@ -288,9 +288,9 @@ impl<'r, D: Database> FromRequest<'r> for Connection<D> {
|
||||||
match D::fetch(req.rocket()) {
|
match D::fetch(req.rocket()) {
|
||||||
Some(db) => match db.get().await {
|
Some(db) => match db.get().await {
|
||||||
Ok(conn) => Outcome::Success(Connection(conn)),
|
Ok(conn) => Outcome::Success(Connection(conn)),
|
||||||
Err(e) => Outcome::Failure((Status::ServiceUnavailable, Some(e))),
|
Err(e) => Outcome::Error((Status::ServiceUnavailable, Some(e))),
|
||||||
},
|
},
|
||||||
None => Outcome::Failure((Status::InternalServerError, None)),
|
None => Outcome::Error((Status::InternalServerError, None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ impl<'r> FromRequest<'r> for Metadata<'r> {
|
||||||
error_!("Uninitialized template context: missing fairing.");
|
error_!("Uninitialized template context: missing fairing.");
|
||||||
info_!("To use templates, you must attach `Template::fairing()`.");
|
info_!("To use templates, you must attach `Template::fairing()`.");
|
||||||
info_!("See the `Template` documentation for more information.");
|
info_!("See the `Template` documentation for more information.");
|
||||||
request::Outcome::Failure((Status::InternalServerError, ()))
|
request::Outcome::Error((Status::InternalServerError, ()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ impl<'r, K: 'static, C: Poolable> FromRequest<'r> for Connection<K, C> {
|
||||||
Some(c) => c.get().await.into_outcome((Status::ServiceUnavailable, ())),
|
Some(c) => c.get().await.into_outcome((Status::ServiceUnavailable, ())),
|
||||||
None => {
|
None => {
|
||||||
error_!("Missing database fairing for `{}`", std::any::type_name::<K>());
|
error_!("Missing database fairing for `{}`", std::any::type_name::<K>());
|
||||||
Outcome::Failure((Status::InternalServerError, ()))
|
Outcome::Error((Status::InternalServerError, ()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,9 +126,9 @@ fn request_guard_decl(guard: &Guard) -> TokenStream {
|
||||||
#_log::warn_!("Request guard `{}` is forwarding.", stringify!(#ty));
|
#_log::warn_!("Request guard `{}` is forwarding.", stringify!(#ty));
|
||||||
return #Outcome::Forward((#__data, __e));
|
return #Outcome::Forward((#__data, __e));
|
||||||
},
|
},
|
||||||
#Outcome::Failure((__c, __e)) => {
|
#Outcome::Error((__c, __e)) => {
|
||||||
#_log::warn_!("Request guard `{}` failed: {:?}.", stringify!(#ty), __e);
|
#_log::warn_!("Request guard `{}` failed: {:?}.", stringify!(#ty), __e);
|
||||||
return #Outcome::Failure(__c);
|
return #Outcome::Error(__c);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -189,9 +189,9 @@ fn data_guard_decl(guard: &Guard) -> TokenStream {
|
||||||
#_log::warn_!("Data guard `{}` is forwarding.", stringify!(#ty));
|
#_log::warn_!("Data guard `{}` is forwarding.", stringify!(#ty));
|
||||||
return #Outcome::Forward((__d, __e));
|
return #Outcome::Forward((__d, __e));
|
||||||
}
|
}
|
||||||
#Outcome::Failure((__c, __e)) => {
|
#Outcome::Error((__c, __e)) => {
|
||||||
#_log::warn_!("Data guard `{}` failed: {:?}.", stringify!(#ty), __e);
|
#_log::warn_!("Data guard `{}` failed: {:?}.", stringify!(#ty), __e);
|
||||||
return #Outcome::Failure(__c);
|
return #Outcome::Error(__c);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,8 +239,7 @@ macro_rules! route_attribute {
|
||||||
///
|
///
|
||||||
/// If a request guard fails, the request is forwarded if the
|
/// If a request guard fails, the request is forwarded if the
|
||||||
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
|
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
|
||||||
/// `Failure`. See [`FromRequest` Outcomes] for further
|
/// `Error`. See [`FromRequest` Outcomes] for further detail.
|
||||||
/// detail.
|
|
||||||
///
|
///
|
||||||
/// 2. Path and query guards in an unspecified order. If a path
|
/// 2. Path and query guards in an unspecified order. If a path
|
||||||
/// or query guard fails, the request is forwarded.
|
/// or query guard fails, the request is forwarded.
|
||||||
|
@ -249,7 +248,7 @@ macro_rules! route_attribute {
|
||||||
///
|
///
|
||||||
/// If a data guard fails, the request is forwarded if the
|
/// If a data guard fails, the request is forwarded if the
|
||||||
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
|
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
|
||||||
/// `Failure`. See [`FromData`] for further detail.
|
/// `Error`. See [`FromData`] for further detail.
|
||||||
///
|
///
|
||||||
/// If all validation succeeds, the decorated function is called.
|
/// If all validation succeeds, the decorated function is called.
|
||||||
/// The returned value is used to generate a [`Response`] via the
|
/// The returned value is used to generate a [`Response`] via the
|
||||||
|
@ -448,7 +447,7 @@ pub fn main(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
/// #[rocket::main]
|
/// #[rocket::main]
|
||||||
/// async fn main() {
|
/// async fn main() {
|
||||||
/// // Recall that an uninspected `Error` will cause a pretty-printed panic,
|
/// // Recall that an uninspected `Error` will cause a pretty-printed panic,
|
||||||
/// // so rest assured failures do not go undetected when using `#[launch]`.
|
/// // so rest assured errors do not go undetected when using `#[launch]`.
|
||||||
/// let _ = rocket().launch().await;
|
/// let _ = rocket().launch().await;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -8,7 +8,7 @@ macro_rules! assert_parse_eq {
|
||||||
match from_str($from) {
|
match from_str($from) {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
if output != expected {
|
if output != expected {
|
||||||
println!("Failure on: {:?}", $from);
|
println!("Error on: {:?}", $from);
|
||||||
assert_eq!(output, expected, "{} != {}", output, expected);
|
assert_eq!(output, expected, "{} != {}", output, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ macro_rules! assert_displays_eq {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
let output_string = output.to_string();
|
let output_string = output.to_string();
|
||||||
if output_string != string {
|
if output_string != string {
|
||||||
println!("Failure on: {:?}", $string);
|
println!("Error on: {:?}", $string);
|
||||||
println!("Got: {:?}", output_string);
|
println!("Got: {:?}", output_string);
|
||||||
println!("Parsed as: {:?}", output);
|
println!("Parsed as: {:?}", output);
|
||||||
panic!("failed");
|
panic!("failed");
|
||||||
|
|
|
@ -533,7 +533,7 @@ impl fmt::Display for Name<'_> {
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::Parse(e) => write!(f, "parse failure: {}", e),
|
Error::Parse(e) => write!(f, "parse error: {}", e),
|
||||||
Error::Incomplete(_) => write!(f, "incomplete certificate data"),
|
Error::Incomplete(_) => write!(f, "incomplete certificate data"),
|
||||||
Error::Trailing(n) => write!(f, "found {} trailing bytes", n),
|
Error::Trailing(n) => write!(f, "found {} trailing bytes", n),
|
||||||
Error::Empty => write!(f, "empty certificate chain"),
|
Error::Empty => write!(f, "empty certificate chain"),
|
||||||
|
|
|
@ -16,12 +16,14 @@ use yansi::Paint;
|
||||||
///
|
///
|
||||||
/// * A failing guard.
|
/// * A failing guard.
|
||||||
/// * A failing responder.
|
/// * A failing responder.
|
||||||
|
/// * A forwarding guard.
|
||||||
/// * Routing failure.
|
/// * Routing failure.
|
||||||
///
|
///
|
||||||
/// Each failure is paired with a status code. Guards and responders indicate
|
/// Each error or forward is paired with a status code. Guards and responders
|
||||||
/// the status code themselves via their `Err` return value while a routing
|
/// indicate the status code themselves via their `Err` and `Outcome` return
|
||||||
/// failure is always a `404`. Rocket invokes the error handler for the catcher
|
/// value. A complete routing failure is always a `404`. Rocket invokes the
|
||||||
/// with the error's status code.
|
/// error handler for the catcher with an error's status code, or in the case of
|
||||||
|
/// every route resulting in a forward, the last forwarded status code.
|
||||||
///
|
///
|
||||||
/// ### Error Handler Restrictions
|
/// ### Error Handler Restrictions
|
||||||
///
|
///
|
||||||
|
@ -31,14 +33,18 @@ use yansi::Paint;
|
||||||
///
|
///
|
||||||
/// # Routing
|
/// # Routing
|
||||||
///
|
///
|
||||||
/// An error arising from a particular request _matches_ a catcher _iff_:
|
/// If a route fails by returning an error [`Outcome`], Rocket routes the
|
||||||
|
/// erroring request to the highest precedence catcher among all the catchers
|
||||||
|
/// that match. Precedence is determined by the catcher's _base_, which is
|
||||||
|
/// provided as the first argument to [`Rocket::register()`]. Catchers with more
|
||||||
|
/// non-empty segments have a higher precedence.
|
||||||
///
|
///
|
||||||
/// * It is a default catcher _or_ has a status code matching the error code.
|
/// Rocket provides [built-in defaults](#built-in-default), but _default_
|
||||||
/// * Its base is a prefix of the normalized/decoded request URI path.
|
/// catchers can also be registered. A _default_ catcher is a catcher with no
|
||||||
|
/// explicit status code: `None`.
|
||||||
///
|
///
|
||||||
/// A _default_ catcher is a catcher with no explicit status code: `None`. The
|
/// [`Outcome`]: crate::request::Outcome
|
||||||
/// catcher's _base_ is provided as the first argument to
|
/// [`Rocket::register()`]: crate::Rocket::register()
|
||||||
/// [`Rocket::register()`](crate::Rocket::register()).
|
|
||||||
///
|
///
|
||||||
/// # Collisions
|
/// # Collisions
|
||||||
///
|
///
|
||||||
|
|
|
@ -288,7 +288,7 @@ impl Config {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If extraction fails, prints an error message indicating the failure and
|
/// If extraction fails, prints an error message indicating the error and
|
||||||
/// panics. For a version that doesn't panic, use [`Config::try_from()`].
|
/// panics. For a version that doesn't panic, use [`Config::try_from()`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
|
@ -52,7 +52,7 @@ enum Kind {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// When running in any other profile with the `secrets` feature enabled,
|
/// When running in any other profile with the `secrets` feature enabled,
|
||||||
/// providing a key of `0` or not provided a key at all results in a failure at
|
/// providing a key of `0` or not provided a key at all results in an error at
|
||||||
/// launch-time:
|
/// launch-time:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -67,7 +67,7 @@ enum Kind {
|
||||||
/// .select(profile.clone());
|
/// .select(profile.clone());
|
||||||
///
|
///
|
||||||
/// let rocket = rocket::custom(figment);
|
/// let rocket = rocket::custom(figment);
|
||||||
/// let error = Client::tracked(rocket).expect_err("failure in non-debug");
|
/// let error = Client::tracked(rocket).expect_err("error in non-debug");
|
||||||
/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile)));
|
/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile)));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
@ -260,10 +260,10 @@ macro_rules! impl_strict_from_data_from_capped {
|
||||||
Success(p) if p.is_complete() => Success(p.into_inner()),
|
Success(p) if p.is_complete() => Success(p.into_inner()),
|
||||||
Success(_) => {
|
Success(_) => {
|
||||||
let e = Error::new(UnexpectedEof, "data limit exceeded");
|
let e = Error::new(UnexpectedEof, "data limit exceeded");
|
||||||
Failure((Status::BadRequest, e.into()))
|
Error((Status::BadRequest, e.into()))
|
||||||
},
|
},
|
||||||
Forward(d) => Forward(d),
|
Forward(d) => Forward(d),
|
||||||
Failure((s, e)) => Failure((s, e)),
|
Error((s, e)) => Error((s, e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,14 @@ pub type Outcome<'r, T, E = <T as FromData<'r>>::Error>
|
||||||
= outcome::Outcome<T, (Status, E), (Data<'r>, Status)>;
|
= outcome::Outcome<T, (Status, E), (Data<'r>, Status)>;
|
||||||
|
|
||||||
impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E> {
|
impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E> {
|
||||||
type Failure = Status;
|
type Error = Status;
|
||||||
type Forward = (Data<'r>, Status);
|
type Forward = (Data<'r>, Status);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_outcome(self, status: Status) -> Outcome<'r, S, E> {
|
fn into_outcome(self, status: Status) -> Outcome<'r, S, E> {
|
||||||
match self {
|
match self {
|
||||||
Ok(val) => Success(val),
|
Ok(val) => Success(val),
|
||||||
Err(err) => Failure((status, err))
|
Err(err) => Error((status, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +251,7 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
|
||||||
/// use rocket::request::{self, Request};
|
/// use rocket::request::{self, Request};
|
||||||
/// use rocket::data::{self, Data, FromData, ToByteUnit};
|
/// use rocket::data::{self, Data, FromData, ToByteUnit};
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
|
/// use rocket::outcome::Outcome;
|
||||||
///
|
///
|
||||||
/// #[derive(Debug)]
|
/// #[derive(Debug)]
|
||||||
/// enum Error {
|
/// enum Error {
|
||||||
|
@ -266,12 +267,11 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
|
||||||
///
|
///
|
||||||
/// async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {
|
/// async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {
|
||||||
/// use Error::*;
|
/// use Error::*;
|
||||||
/// use rocket::outcome::Outcome::*;
|
|
||||||
///
|
///
|
||||||
/// // Ensure the content type is correct before opening the data.
|
/// // Ensure the content type is correct before opening the data.
|
||||||
/// let person_ct = ContentType::new("application", "x-person");
|
/// let person_ct = ContentType::new("application", "x-person");
|
||||||
/// if req.content_type() != Some(&person_ct) {
|
/// if req.content_type() != Some(&person_ct) {
|
||||||
/// return Forward((data, Status::NotFound));
|
/// return Outcome::Forward((data, Status::NotFound));
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// // Use a configured limit with name 'person' or fallback to default.
|
/// // Use a configured limit with name 'person' or fallback to default.
|
||||||
|
@ -280,8 +280,8 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
|
||||||
/// // Read the data into a string.
|
/// // Read the data into a string.
|
||||||
/// let string = match data.open(limit).into_string().await {
|
/// let string = match data.open(limit).into_string().await {
|
||||||
/// Ok(string) if string.is_complete() => string.into_inner(),
|
/// Ok(string) if string.is_complete() => string.into_inner(),
|
||||||
/// Ok(_) => return Failure((Status::PayloadTooLarge, TooLarge)),
|
/// Ok(_) => return Outcome::Error((Status::PayloadTooLarge, TooLarge)),
|
||||||
/// Err(e) => return Failure((Status::InternalServerError, Io(e))),
|
/// Err(e) => return Outcome::Error((Status::InternalServerError, Io(e))),
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// // We store `string` in request-local cache for long-lived borrows.
|
/// // We store `string` in request-local cache for long-lived borrows.
|
||||||
|
@ -290,16 +290,16 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
|
||||||
/// // Split the string into two pieces at ':'.
|
/// // Split the string into two pieces at ':'.
|
||||||
/// let (name, age) = match string.find(':') {
|
/// let (name, age) = match string.find(':') {
|
||||||
/// Some(i) => (&string[..i], &string[(i + 1)..]),
|
/// Some(i) => (&string[..i], &string[(i + 1)..]),
|
||||||
/// None => return Failure((Status::UnprocessableEntity, NoColon)),
|
/// None => return Outcome::Error((Status::UnprocessableEntity, NoColon)),
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// // Parse the age.
|
/// // Parse the age.
|
||||||
/// let age: u16 = match age.parse() {
|
/// let age: u16 = match age.parse() {
|
||||||
/// Ok(age) => age,
|
/// Ok(age) => age,
|
||||||
/// Err(_) => return Failure((Status::UnprocessableEntity, InvalidAge)),
|
/// Err(_) => return Outcome::Error((Status::UnprocessableEntity, InvalidAge)),
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// Success(Person { name, age })
|
/// Outcome::Success(Person { name, age })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -331,7 +331,7 @@ pub trait FromData<'r>: Sized {
|
||||||
///
|
///
|
||||||
/// If validation and parsing succeeds, an outcome of `Success` is returned.
|
/// If validation and parsing succeeds, an outcome of `Success` is returned.
|
||||||
/// If the data is not appropriate given the type of `Self`, `Forward` is
|
/// If the data is not appropriate given the type of `Self`, `Forward` is
|
||||||
/// returned. If parsing fails, `Failure` is returned.
|
/// returned. If parsing fails, `Error` is returned.
|
||||||
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self>;
|
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +428,7 @@ impl<'r, T: FromData<'r> + 'r> FromData<'r> for Result<T, T::Error> {
|
||||||
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
||||||
match T::from_data(req, data).await {
|
match T::from_data(req, data).await {
|
||||||
Success(v) => Success(Ok(v)),
|
Success(v) => Success(Ok(v)),
|
||||||
Failure((_, e)) => Success(Err(e)),
|
Error((_, e)) => Success(Err(e)),
|
||||||
Forward(d) => Forward(d),
|
Forward(d) => Forward(d),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
|
||||||
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
||||||
match T::from_data(req, data).await {
|
match T::from_data(req, data).await {
|
||||||
Success(v) => Success(Some(v)),
|
Success(v) => Success(Some(v)),
|
||||||
Failure(..) | Forward(..) => Success(None),
|
Error(..) | Forward(..) => Success(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,9 +212,9 @@ impl Error {
|
||||||
crate::config::pretty_print_error(error.clone());
|
crate::config::pretty_print_error(error.clone());
|
||||||
"aborting due to invalid configuration"
|
"aborting due to invalid configuration"
|
||||||
}
|
}
|
||||||
ErrorKind::SentinelAborts(ref failures) => {
|
ErrorKind::SentinelAborts(ref errors) => {
|
||||||
error!("Rocket failed to launch due to aborting sentinels:");
|
error!("Rocket failed to launch due to aborting sentinels:");
|
||||||
for sentry in failures {
|
for sentry in errors {
|
||||||
let name = sentry.type_name.primary().bold();
|
let name = sentry.type_name.primary().bold();
|
||||||
let (file, line, col) = sentry.location;
|
let (file, line, col) = sentry.location;
|
||||||
info_!("{} ({}:{}:{})", name, file, line, col);
|
info_!("{} ({}:{}:{})", name, file, line, col);
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
|
||||||
|
|
||||||
// We might imagine that a request fairing returns an `Outcome`. If it returns
|
// We might imagine that a request fairing returns an `Outcome`. If it returns
|
||||||
// `Success`, we don't do any routing and use that response directly. Same if it
|
// `Success`, we don't do any routing and use that response directly. Same if it
|
||||||
// returns `Failure`. We only route if it returns `Forward`. I've chosen not to
|
// returns `Error`. We only route if it returns `Forward`. I've chosen not to
|
||||||
// go this direction because I feel like request guards are the correct
|
// go this direction because I feel like request guards are the correct
|
||||||
// mechanism to use here. In other words, enabling this at the fairing level
|
// mechanism to use here. In other words, enabling this at the fairing level
|
||||||
// encourages implicit handling, a bad practice. Fairings can still, however,
|
// encourages implicit handling, a bad practice. Fairings can still, however,
|
||||||
|
@ -125,7 +125,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
|
||||||
/// recursively attaching ignite fairings. It returns `Ok` if it would like
|
/// recursively attaching ignite fairings. It returns `Ok` if it would like
|
||||||
/// ignition and launch to proceed nominally and `Err` otherwise. If an
|
/// ignition and launch to proceed nominally and `Err` otherwise. If an
|
||||||
/// ignite fairing returns `Err`, launch will be aborted. All ignite
|
/// ignite fairing returns `Err`, launch will be aborted. All ignite
|
||||||
/// fairings are executed even if one or more signal a failure.
|
/// fairings are executed even if one or more signal an error.
|
||||||
///
|
///
|
||||||
/// * **<a name="liftoff">Liftoff</a> (`on_liftoff`)**
|
/// * **<a name="liftoff">Liftoff</a> (`on_liftoff`)**
|
||||||
///
|
///
|
||||||
|
@ -417,7 +417,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
|
||||||
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
||||||
/// match *request.local_cache(|| TimerStart(None)) {
|
/// match *request.local_cache(|| TimerStart(None)) {
|
||||||
/// TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),
|
/// TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),
|
||||||
/// TimerStart(None) => request::Outcome::Failure((Status::InternalServerError, ())),
|
/// TimerStart(None) => request::Outcome::Error((Status::InternalServerError, ())),
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -350,7 +350,7 @@ impl<'v> Errors<'v> {
|
||||||
/// Returns the highest [`Error::status()`] of all of the errors in `self`
|
/// Returns the highest [`Error::status()`] of all of the errors in `self`
|
||||||
/// or [`Status::InternalServerError`] if `self` is empty. This is the
|
/// or [`Status::InternalServerError`] if `self` is empty. This is the
|
||||||
/// status that is set by the [`Form`](crate::form::Form) data guard on
|
/// status that is set by the [`Form`](crate::form::Form) data guard on
|
||||||
/// failure.
|
/// error.
|
||||||
///
|
///
|
||||||
/// See [`Error::status()`] for the corresponding status code of each
|
/// See [`Error::status()`] for the corresponding status code of each
|
||||||
/// [`Error`] variant.
|
/// [`Error`] variant.
|
||||||
|
|
|
@ -65,8 +65,8 @@ use crate::form::prelude::*;
|
||||||
///
|
///
|
||||||
/// If the request `ContentType` _does_ identify as a form but the form data
|
/// If the request `ContentType` _does_ identify as a form but the form data
|
||||||
/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the
|
/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the
|
||||||
/// guard **fails**. The `Failure` variant contains of the [`Errors`] emitted by
|
/// guard **fails**. The `Error` variant contains a vector of the [`Errors`]
|
||||||
/// `T`'s `FromForm` parser. If the error is not caught by a
|
/// emitted by `T`'s `FromForm` parser. If the error is not caught by a
|
||||||
/// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code
|
/// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code
|
||||||
/// is set to [`Errors::status()`], and the corresponding error catcher is
|
/// is set to [`Errors::status()`], and the corresponding error catcher is
|
||||||
/// called.
|
/// called.
|
||||||
|
@ -334,7 +334,7 @@ impl<'r, T: FromForm<'r>> FromData<'r> for Form<T> {
|
||||||
|
|
||||||
match T::finalize(context) {
|
match T::finalize(context) {
|
||||||
Ok(value) => Outcome::Success(Form(value)),
|
Ok(value) => Outcome::Success(Form(value)),
|
||||||
Err(e) => Outcome::Failure((e.status(), e)),
|
Err(e) => Outcome::Error((e.status(), e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,7 +297,7 @@ impl<'v> FromFormField<'v> for Capped<&'v str> {
|
||||||
|
|
||||||
match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await {
|
match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await {
|
||||||
Outcome::Success(p) => Ok(p),
|
Outcome::Success(p) => Ok(p),
|
||||||
Outcome::Failure((_, e)) => Err(e)?,
|
Outcome::Error((_, e)) => Err(e)?,
|
||||||
Outcome::Forward(..) => {
|
Outcome::Forward(..) => {
|
||||||
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ impl<'v> FromFormField<'v> for Capped<String> {
|
||||||
|
|
||||||
match <Capped<String> as FromData>::from_data(f.request, f.data).await {
|
match <Capped<String> as FromData>::from_data(f.request, f.data).await {
|
||||||
Outcome::Success(p) => Ok(p),
|
Outcome::Success(p) => Ok(p),
|
||||||
Outcome::Failure((_, e)) => Err(e)?,
|
Outcome::Error((_, e)) => Err(e)?,
|
||||||
Outcome::Forward(..) => {
|
Outcome::Forward(..) => {
|
||||||
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ impl<'v> FromFormField<'v> for Capped<&'v [u8]> {
|
||||||
|
|
||||||
match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await {
|
match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await {
|
||||||
Outcome::Success(p) => Ok(p),
|
Outcome::Success(p) => Ok(p),
|
||||||
Outcome::Failure((_, e)) => Err(e)?,
|
Outcome::Error((_, e)) => Err(e)?,
|
||||||
Outcome::Forward(..) => {
|
Outcome::Forward(..) => {
|
||||||
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl<'r, 'i> Parser<'r, 'i> {
|
||||||
|
|
||||||
match parser {
|
match parser {
|
||||||
Ok(storage) => Outcome::Success(storage),
|
Ok(storage) => Outcome::Success(storage),
|
||||||
Err(e) => Outcome::Failure((e.status(), e.into()))
|
Err(e) => Outcome::Error((e.status(), e.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ crate::export! {
|
||||||
|
|
||||||
/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].
|
/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the following message:
|
/// On error, returns a validation error with the following message:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// value does not match expected value
|
/// value does not match expected value
|
||||||
|
@ -236,7 +236,7 @@ pub fn dbg_eq<'v, A, B>(a: &A, b: B) -> Result<'v, ()>
|
||||||
/// Negative equality validator: succeeds exactly when `a` != `b`, using
|
/// Negative equality validator: succeeds exactly when `a` != `b`, using
|
||||||
/// [`PartialEq`].
|
/// [`PartialEq`].
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the following message:
|
/// On error, returns a validation error with the following message:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// value is equal to an invalid value
|
/// value is equal to an invalid value
|
||||||
|
@ -361,7 +361,7 @@ impl<L, T: Len<L>> Len<L> for crate::serde::msgpack::MsgPack<T> {
|
||||||
|
|
||||||
/// Length validator: succeeds when the length of a value is within a `range`.
|
/// Length validator: succeeds when the length of a value is within a `range`.
|
||||||
///
|
///
|
||||||
/// The value must implement [`Len`]. On failure, returns an [`InvalidLength`]
|
/// The value must implement [`Len`]. On error, returns an [`InvalidLength`]
|
||||||
/// error. See [`Len`] for supported types and how their length is computed.
|
/// error. See [`Len`] for supported types and how their length is computed.
|
||||||
///
|
///
|
||||||
/// [`InvalidLength`]: crate::form::error::ErrorKind::InvalidLength
|
/// [`InvalidLength`]: crate::form::error::ErrorKind::InvalidLength
|
||||||
|
@ -504,7 +504,7 @@ impl<I, T: Contains<I> + ?Sized> Contains<I> for &T {
|
||||||
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
|
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
|
||||||
/// [`Contains`] for supported types and items.
|
/// [`Contains`] for supported types and items.
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the following message:
|
/// On error, returns a validation error with the following message:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// value is equal to an invalid value
|
/// value is equal to an invalid value
|
||||||
|
@ -590,7 +590,7 @@ pub fn dbg_contains<'v, V, I>(value: V, item: I) -> Result<'v, ()>
|
||||||
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
|
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
|
||||||
/// [`Contains`] for supported types and items.
|
/// [`Contains`] for supported types and items.
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the following message:
|
/// On error, returns a validation error with the following message:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// value contains a disallowed item
|
/// value contains a disallowed item
|
||||||
|
@ -670,7 +670,7 @@ pub fn dbg_omits<'v, V, I>(value: V, item: I) -> Result<'v, ()>
|
||||||
/// Integer range validator: succeeds when an integer value is within a range.
|
/// Integer range validator: succeeds when an integer value is within a range.
|
||||||
///
|
///
|
||||||
/// The value must be an integer type that implement `TryInto<isize> + Copy`. On
|
/// The value must be an integer type that implement `TryInto<isize> + Copy`. On
|
||||||
/// failure, returns an [`OutOfRange`] error.
|
/// error, returns an [`OutOfRange`] error.
|
||||||
///
|
///
|
||||||
/// [`OutOfRange`]: crate::form::error::ErrorKind::OutOfRange
|
/// [`OutOfRange`]: crate::form::error::ErrorKind::OutOfRange
|
||||||
///
|
///
|
||||||
|
@ -719,7 +719,7 @@ pub fn range<'v, V, R>(value: &V, range: R) -> Result<'v, ()>
|
||||||
/// the `item`. The iterator must be [`Clone`]. See [`Contains`] for supported
|
/// the `item`. The iterator must be [`Clone`]. See [`Contains`] for supported
|
||||||
/// types and items. The item must be [`Debug`].
|
/// types and items. The item must be [`Debug`].
|
||||||
///
|
///
|
||||||
/// On failure, returns a [`InvalidChoice`] error with the debug representation
|
/// On error, returns a [`InvalidChoice`] error with the debug representation
|
||||||
/// of each item in `items`.
|
/// of each item in `items`.
|
||||||
///
|
///
|
||||||
/// [`InvalidChoice`]: crate::form::error::ErrorKind::InvalidChoice
|
/// [`InvalidChoice`]: crate::form::error::ErrorKind::InvalidChoice
|
||||||
|
@ -762,7 +762,7 @@ pub fn one_of<'v, V, I, R>(value: V, items: R) -> Result<'v, ()>
|
||||||
/// File type validator: succeeds when a [`TempFile`] has the Content-Type
|
/// File type validator: succeeds when a [`TempFile`] has the Content-Type
|
||||||
/// `content_type`.
|
/// `content_type`.
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with one of the following messages:
|
/// On error, returns a validation error with one of the following messages:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// // the file has an incorrect extension
|
/// // the file has an incorrect extension
|
||||||
|
@ -810,7 +810,7 @@ pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {
|
||||||
/// when a more case-specific option does not exist. It succeeds exactly when
|
/// when a more case-specific option does not exist. It succeeds exactly when
|
||||||
/// `f` returns `true` and fails otherwise.
|
/// `f` returns `true` and fails otherwise.
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the message `msg`.
|
/// On error, returns a validation error with the message `msg`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -860,7 +860,7 @@ pub fn with<'v, V, F, M>(value: V, f: F, msg: M) -> Result<'v, ()>
|
||||||
/// Along with [`with`], this is the most generic validator. It succeeds
|
/// Along with [`with`], this is the most generic validator. It succeeds
|
||||||
/// exactly when `f` returns `Ok` and fails otherwise.
|
/// exactly when `f` returns `Ok` and fails otherwise.
|
||||||
///
|
///
|
||||||
/// On failure, returns a validation error with the message in the `Err`
|
/// On error, returns a validation error with the message in the `Err`
|
||||||
/// variant converted into a string.
|
/// variant converted into a string.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
|
@ -149,12 +149,12 @@ impl FileServer {
|
||||||
if !options.contains(Options::IndexFile) && !path.is_dir() {
|
if !options.contains(Options::IndexFile) && !path.is_dir() {
|
||||||
let path = path.display();
|
let path = path.display();
|
||||||
error!("FileServer path '{}' is not a directory.", path.primary());
|
error!("FileServer path '{}' is not a directory.", path.primary());
|
||||||
warn_!("Aborting early to prevent inevitable handler failure.");
|
warn_!("Aborting early to prevent inevitable handler error.");
|
||||||
panic!("invalid directory: refusing to continue");
|
panic!("invalid directory: refusing to continue");
|
||||||
} else if !path.exists() {
|
} else if !path.exists() {
|
||||||
let path = path.display();
|
let path = path.display();
|
||||||
error!("FileServer path '{}' is not a file.", path.primary());
|
error!("FileServer path '{}' is not a file.", path.primary());
|
||||||
warn_!("Aborting early to prevent inevitable handler failure.");
|
warn_!("Aborting early to prevent inevitable handler error.");
|
||||||
panic!("invalid file: refusing to continue");
|
panic!("invalid file: refusing to continue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! Success, failure, and forward handling.
|
//! Success, error, and forward handling.
|
||||||
//!
|
//!
|
||||||
//! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S,
|
//! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S,
|
||||||
//! E>` type. It is an enum with three variants, each containing a value:
|
//! E>` type. It is an enum with three variants, each containing a value:
|
||||||
//! `Success(S)`, which represents a successful outcome, `Failure(E)`, which
|
//! `Success(S)`, which represents a successful outcome, `Error(E)`, which
|
||||||
//! represents a failing outcome, and `Forward(F)`, which represents neither a
|
//! represents an erroring outcome, and `Forward(F)`, which represents neither a
|
||||||
//! success or failure, but instead, indicates that processing could not be
|
//! success or error, but instead, indicates that processing could not be
|
||||||
//! handled and should instead be _forwarded_ to whatever can handle the
|
//! handled and should instead be _forwarded_ to whatever can handle the
|
||||||
//! processing next.
|
//! processing next.
|
||||||
//!
|
//!
|
||||||
|
@ -35,15 +35,15 @@
|
||||||
//! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will
|
//! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will
|
||||||
//! be unwrapped and the value will be used as the value of `my_val`.
|
//! be unwrapped and the value will be used as the value of `my_val`.
|
||||||
//!
|
//!
|
||||||
//! # Failure
|
//! # Error
|
||||||
//!
|
//!
|
||||||
//! A failure `Outcome<S, E, F>`, `Failure(E)`, is returned when a function
|
//! An error `Outcome<S, E, F>`, `Error(E)`, is returned when a function
|
||||||
//! fails with some error and no processing can or should continue as a result.
|
//! fails with some error and no processing can or should continue as a result.
|
||||||
//! The meaning of a failure depends on the context.
|
//! The meaning of an error depends on the context.
|
||||||
//!
|
//!
|
||||||
//! In Rocket, a `Failure` generally means that a request is taken out of normal
|
//! In Rocket, an `Error` generally means that a request is taken out of normal
|
||||||
//! processing. The request is then given to the catcher corresponding to some
|
//! processing. The request is then given to the catcher corresponding to some
|
||||||
//! status code. Users can catch failures by requesting a type of `Result<S, E>`
|
//! status code. Users can catch errors by requesting a type of `Result<S, E>`
|
||||||
//! or `Option<S>` in request handlers. For example, if a user's handler looks
|
//! or `Option<S>` in request handlers. For example, if a user's handler looks
|
||||||
//! like:
|
//! like:
|
||||||
//!
|
//!
|
||||||
|
@ -56,10 +56,9 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
|
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
|
||||||
//! `Success(S)` and `Failure(E)`. If `from_data` returns a `Failure`, the
|
//! `Success(S)` and `Error(E)`. If `from_data` returns an `Error`, the `Error`
|
||||||
//! `Failure` value will be unwrapped and the value will be used as the `Err`
|
//! value will be unwrapped and the value will be used as the `Err` value of
|
||||||
//! value of `my_val` while a `Success` will be unwrapped and used the `Ok`
|
//! `my_val` while a `Success` will be unwrapped and used the `Ok` value.
|
||||||
//! value.
|
|
||||||
//!
|
//!
|
||||||
//! # Forward
|
//! # Forward
|
||||||
//!
|
//!
|
||||||
|
@ -79,11 +78,11 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
|
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
|
||||||
//! `Success(S)`, `Failure(E)`, and `Forward(F)`. If the `Outcome` is a
|
//! `Success(S)`, `Error(E)`, and `Forward(F)`. If the `Outcome` is a
|
||||||
//! `Forward`, the `hello` handler isn't called. Instead, the incoming request
|
//! `Forward`, the `hello` handler isn't called. Instead, the incoming request
|
||||||
//! is forwarded, or passed on to, the next matching route, if any. Ultimately,
|
//! is forwarded, or passed on to, the next matching route, if any. Ultimately,
|
||||||
//! if there are no non-forwarding routes, forwarded requests are handled by the
|
//! if there are no non-forwarding routes, forwarded requests are handled by the
|
||||||
//! 404 catcher. Similar to `Failure`s, users can catch `Forward`s by requesting
|
//! 404 catcher. Similar to `Error`s, users can catch `Forward`s by requesting
|
||||||
//! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be
|
//! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be
|
||||||
//! `None`.
|
//! `None`.
|
||||||
|
|
||||||
|
@ -93,8 +92,8 @@ use yansi::{Paint, Color};
|
||||||
|
|
||||||
use self::Outcome::*;
|
use self::Outcome::*;
|
||||||
|
|
||||||
/// An enum representing success (`Success`), failure (`Failure`), or
|
/// An enum representing success (`Success`), error (`Error`), or forwarding
|
||||||
/// forwarding (`Forward`).
|
/// (`Forward`).
|
||||||
///
|
///
|
||||||
/// See the [top level documentation](crate::outcome) for detailed information.
|
/// See the [top level documentation](crate::outcome) for detailed information.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -102,24 +101,24 @@ use self::Outcome::*;
|
||||||
pub enum Outcome<S, E, F> {
|
pub enum Outcome<S, E, F> {
|
||||||
/// Contains the success value.
|
/// Contains the success value.
|
||||||
Success(S),
|
Success(S),
|
||||||
/// Contains the failure error value.
|
/// Contains the error error value.
|
||||||
Failure(E),
|
Error(E),
|
||||||
/// Contains the value to forward on.
|
/// Contains the value to forward on.
|
||||||
Forward(F),
|
Forward(F),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conversion trait from some type into an Outcome type.
|
/// Conversion trait from some type into an Outcome type.
|
||||||
pub trait IntoOutcome<S, E, F> {
|
pub trait IntoOutcome<S, E, F> {
|
||||||
/// The type to use when returning an `Outcome::Failure`.
|
/// The type to use when returning an `Outcome::Error`.
|
||||||
type Failure: Sized;
|
type Error: Sized;
|
||||||
|
|
||||||
/// The type to use when returning an `Outcome::Forward`.
|
/// The type to use when returning an `Outcome::Forward`.
|
||||||
type Forward: Sized;
|
type Forward: Sized;
|
||||||
|
|
||||||
/// Converts `self` into an `Outcome`. If `self` represents a success, an
|
/// Converts `self` into an `Outcome`. If `self` represents a success, an
|
||||||
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Failure` is
|
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Error` is
|
||||||
/// returned with `failure` as the inner value.
|
/// returned with `error` as the inner value.
|
||||||
fn into_outcome(self, failure: Self::Failure) -> Outcome<S, E, F>;
|
fn into_outcome(self, error: Self::Error) -> Outcome<S, E, F>;
|
||||||
|
|
||||||
/// Converts `self` into an `Outcome`. If `self` represents a success, an
|
/// Converts `self` into an `Outcome`. If `self` represents a success, an
|
||||||
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is
|
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is
|
||||||
|
@ -128,14 +127,14 @@ pub trait IntoOutcome<S, E, F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, E, F> IntoOutcome<S, E, F> for Option<S> {
|
impl<S, E, F> IntoOutcome<S, E, F> for Option<S> {
|
||||||
type Failure = E;
|
type Error = E;
|
||||||
type Forward = F;
|
type Forward = F;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_outcome(self, failure: E) -> Outcome<S, E, F> {
|
fn into_outcome(self, error: E) -> Outcome<S, E, F> {
|
||||||
match self {
|
match self {
|
||||||
Some(val) => Success(val),
|
Some(val) => Success(val),
|
||||||
None => Failure(failure)
|
None => Error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +207,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.is_success(), true);
|
/// assert_eq!(x.is_success(), true);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.is_success(), false);
|
/// assert_eq!(x.is_success(), false);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -219,7 +218,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
matches!(self, Success(_))
|
matches!(self, Success(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this `Outcome` is a `Failure`.
|
/// Return true if this `Outcome` is an `Error`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -228,17 +227,17 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// # use rocket::outcome::Outcome::*;
|
/// # use rocket::outcome::Outcome::*;
|
||||||
/// #
|
/// #
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.is_failure(), false);
|
/// assert_eq!(x.is_error(), false);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.is_failure(), true);
|
/// assert_eq!(x.is_error(), true);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
/// assert_eq!(x.is_failure(), false);
|
/// assert_eq!(x.is_error(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_failure(&self) -> bool {
|
pub fn is_error(&self) -> bool {
|
||||||
matches!(self, Failure(_))
|
matches!(self, Error(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this `Outcome` is a `Forward`.
|
/// Return true if this `Outcome` is a `Forward`.
|
||||||
|
@ -252,7 +251,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.is_forward(), false);
|
/// assert_eq!(x.is_forward(), false);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.is_forward(), false);
|
/// assert_eq!(x.is_forward(), false);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -275,7 +274,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.succeeded(), Some(10));
|
/// assert_eq!(x.succeeded(), Some(10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.succeeded(), None);
|
/// assert_eq!(x.succeeded(), None);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -291,7 +290,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
|
|
||||||
/// Converts from `Outcome<S, E, F>` to `Option<E>`.
|
/// Converts from `Outcome<S, E, F>` to `Option<E>`.
|
||||||
///
|
///
|
||||||
/// Returns the `Some` of the `Failure` if this is a `Failure`, otherwise
|
/// Returns the `Some` of the `Error` if this is an `Error`, otherwise
|
||||||
/// returns `None`. `self` is consumed, and all other values are discarded.
|
/// returns `None`. `self` is consumed, and all other values are discarded.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -301,7 +300,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.failed(), None);
|
/// assert_eq!(x.failed(), None);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.failed(), Some("Hi! I'm an error."));
|
/// assert_eq!(x.failed(), Some("Hi! I'm an error."));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -310,7 +309,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn failed(self) -> Option<E> {
|
pub fn failed(self) -> Option<E> {
|
||||||
match self {
|
match self {
|
||||||
Failure(val) => Some(val),
|
Error(val) => Some(val),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +326,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.forwarded(), None);
|
/// assert_eq!(x.forwarded(), None);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.forwarded(), None);
|
/// assert_eq!(x.forwarded(), None);
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -355,7 +354,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.success_or(false), Ok(10));
|
/// assert_eq!(x.success_or(false), Ok(10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.success_or(false), Err(false));
|
/// assert_eq!(x.success_or(false), Err(false));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -384,7 +383,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.success_or_else(|| false), Ok(10));
|
/// assert_eq!(x.success_or_else(|| false), Ok(10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.success_or_else(|| false), Err(false));
|
/// assert_eq!(x.success_or_else(|| false), Err(false));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
/// let x: Outcome<i32, &str, usize> = Forward(25);
|
||||||
|
@ -407,14 +406,14 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.as_ref(), Success(&10));
|
/// assert_eq!(x.as_ref(), Success(&10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
|
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
|
||||||
/// assert_eq!(x.as_ref(), Failure(&"Hi! I'm an error."));
|
/// assert_eq!(x.as_ref(), Error(&"Hi! I'm an error."));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ref(&self) -> Outcome<&S, &E, &F> {
|
pub fn as_ref(&self) -> Outcome<&S, &E, &F> {
|
||||||
match *self {
|
match *self {
|
||||||
Success(ref val) => Success(val),
|
Success(ref val) => Success(val),
|
||||||
Failure(ref val) => Failure(val),
|
Error(ref val) => Error(val),
|
||||||
Forward(ref val) => Forward(val),
|
Forward(ref val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +435,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> {
|
pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> {
|
||||||
match *self {
|
match *self {
|
||||||
Success(ref mut val) => Success(val),
|
Success(ref mut val) => Success(val),
|
||||||
Failure(ref mut val) => Failure(val),
|
Error(ref mut val) => Error(val),
|
||||||
Forward(ref mut val) => Forward(val),
|
Forward(ref mut val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,29 +457,29 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> {
|
pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => Success(f(val)),
|
Success(val) => Success(f(val)),
|
||||||
Failure(val) => Failure(val),
|
Error(val) => Error(val),
|
||||||
Forward(val) => Forward(val),
|
Forward(val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the `Failure` value using `f`. Maps an `Outcome<S, E, F>` to an
|
/// Maps the `Error` value using `f`. Maps an `Outcome<S, E, F>` to an
|
||||||
/// `Outcome<S, T, F>` by applying the function `f` to the value of type `E`
|
/// `Outcome<S, T, F>` by applying the function `f` to the value of type `E`
|
||||||
/// in `self` if `self` is an `Outcome::Failure`.
|
/// in `self` if `self` is an `Outcome::Error`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rocket::outcome::Outcome;
|
/// # use rocket::outcome::Outcome;
|
||||||
/// # use rocket::outcome::Outcome::*;
|
/// # use rocket::outcome::Outcome::*;
|
||||||
/// #
|
/// #
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("hi");
|
/// let x: Outcome<i32, &str, usize> = Error("hi");
|
||||||
///
|
///
|
||||||
/// let mapped = x.map_failure(|v| if v == "hi" { 10 } else { 0 });
|
/// let mapped = x.map_error(|v| if v == "hi" { 10 } else { 0 });
|
||||||
/// assert_eq!(mapped, Failure(10));
|
/// assert_eq!(mapped, Error(10));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn map_failure<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {
|
pub fn map_error<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => Success(val),
|
Success(val) => Success(val),
|
||||||
Failure(val) => Failure(f(val)),
|
Error(val) => Error(f(val)),
|
||||||
Forward(val) => Forward(val),
|
Forward(val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,7 +501,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> {
|
pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => Success(val),
|
Success(val) => Success(val),
|
||||||
Failure(val) => Failure(val),
|
Error(val) => Error(val),
|
||||||
Forward(val) => Forward(f(val)),
|
Forward(val) => Forward(f(val)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,7 +522,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let mapped = x.and_then(|v| match v {
|
/// let mapped = x.and_then(|v| match v {
|
||||||
/// 10 => Success("10"),
|
/// 10 => Success("10"),
|
||||||
/// 1 => Forward(false),
|
/// 1 => Forward(false),
|
||||||
/// _ => Failure("30")
|
/// _ => Error("30")
|
||||||
/// });
|
/// });
|
||||||
///
|
///
|
||||||
/// assert_eq!(mapped, Success("10"));
|
/// assert_eq!(mapped, Success("10"));
|
||||||
|
@ -532,15 +531,15 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> {
|
pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => f(val),
|
Success(val) => f(val),
|
||||||
Failure(val) => Failure(val),
|
Error(val) => Error(val),
|
||||||
Forward(val) => Forward(val),
|
Forward(val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map
|
/// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map
|
||||||
/// `Failure(E)` to `Failure(T)`.
|
/// `Error(E)` to `Error(T)`.
|
||||||
///
|
///
|
||||||
/// If `self` is not `Failure`, `self` is returned.
|
/// If `self` is not `Error`, `self` is returned.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -548,21 +547,21 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// # use rocket::outcome::Outcome;
|
/// # use rocket::outcome::Outcome;
|
||||||
/// # use rocket::outcome::Outcome::*;
|
/// # use rocket::outcome::Outcome::*;
|
||||||
/// #
|
/// #
|
||||||
/// let x: Outcome<i32, &str, bool> = Failure("hi");
|
/// let x: Outcome<i32, &str, bool> = Error("hi");
|
||||||
///
|
///
|
||||||
/// let mapped = x.failure_then(|v| match v {
|
/// let mapped = x.error_then(|v| match v {
|
||||||
/// "hi" => Failure(10),
|
/// "hi" => Error(10),
|
||||||
/// "test" => Forward(false),
|
/// "test" => Forward(false),
|
||||||
/// _ => Success(10)
|
/// _ => Success(10)
|
||||||
/// });
|
/// });
|
||||||
///
|
///
|
||||||
/// assert_eq!(mapped, Failure(10));
|
/// assert_eq!(mapped, Error(10));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn failure_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> {
|
pub fn error_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => Success(val),
|
Success(val) => Success(val),
|
||||||
Failure(val) => f(val),
|
Error(val) => f(val),
|
||||||
Forward(val) => Forward(val),
|
Forward(val) => Forward(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,7 +582,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let mapped = x.forward_then(|v| match v {
|
/// let mapped = x.forward_then(|v| match v {
|
||||||
/// Some(true) => Success(10),
|
/// Some(true) => Success(10),
|
||||||
/// Some(false) => Forward(20),
|
/// Some(false) => Forward(20),
|
||||||
/// None => Failure("10")
|
/// None => Error("10")
|
||||||
/// });
|
/// });
|
||||||
///
|
///
|
||||||
/// assert_eq!(mapped, Forward(20));
|
/// assert_eq!(mapped, Forward(20));
|
||||||
|
@ -592,13 +591,13 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> {
|
pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> {
|
||||||
match self {
|
match self {
|
||||||
Success(val) => Success(val),
|
Success(val) => Success(val),
|
||||||
Failure(val) => Failure(val),
|
Error(val) => Error(val),
|
||||||
Forward(val) => f(val),
|
Forward(val) => f(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
|
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
|
||||||
/// `Success(S)` and `Failure(E)` to `Result<T, E>` and mapping `Forward(F)`
|
/// `Success(S)` and `Error(E)` to `Result<T, E>` and mapping `Forward(F)`
|
||||||
/// to `Result<T, E>` using `f`.
|
/// to `Result<T, E>` using `f`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -608,7 +607,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10));
|
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("hello");
|
/// let x: Outcome<i32, &str, usize> = Error("hello");
|
||||||
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err("hello"));
|
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err("hello"));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(0);
|
/// let x: Outcome<i32, &str, usize> = Forward(0);
|
||||||
|
@ -620,13 +619,13 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Outcome::Success(s) => Ok(s),
|
Outcome::Success(s) => Ok(s),
|
||||||
Outcome::Failure(e) => Err(e),
|
Outcome::Error(e) => Err(e),
|
||||||
Outcome::Forward(v) => f(v),
|
Outcome::Forward(v) => f(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
|
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
|
||||||
/// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Failure(E)`
|
/// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Error(E)`
|
||||||
/// to `Result<T, F>` using `f`.
|
/// to `Result<T, F>` using `f`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -634,21 +633,21 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
/// # use rocket::outcome::Outcome::*;
|
/// # use rocket::outcome::Outcome::*;
|
||||||
/// #
|
/// #
|
||||||
/// let x: Outcome<i32, &str, usize> = Success(10);
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Ok(10));
|
/// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(10));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Failure("hello");
|
/// let x: Outcome<i32, &str, usize> = Error("hello");
|
||||||
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Ok(123));
|
/// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(123));
|
||||||
///
|
///
|
||||||
/// let x: Outcome<i32, &str, usize> = Forward(0);
|
/// let x: Outcome<i32, &str, usize> = Forward(0);
|
||||||
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Err(0));
|
/// assert_eq!(x.ok_map_error(|s| Ok(123)), Err(0));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ok_map_failure<M>(self, f: M) -> Result<S, F>
|
pub fn ok_map_error<M>(self, f: M) -> Result<S, F>
|
||||||
where M: FnOnce(E) -> Result<S, F>
|
where M: FnOnce(E) -> Result<S, F>
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Outcome::Success(s) => Ok(s),
|
Outcome::Success(s) => Ok(s),
|
||||||
Outcome::Failure(e) => f(e),
|
Outcome::Error(e) => f(e),
|
||||||
Outcome::Forward(v) => Err(v),
|
Outcome::Forward(v) => Err(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +656,7 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
fn formatting(&self) -> (Color, &'static str) {
|
fn formatting(&self) -> (Color, &'static str) {
|
||||||
match *self {
|
match *self {
|
||||||
Success(..) => (Color::Green, "Success"),
|
Success(..) => (Color::Green, "Success"),
|
||||||
Failure(..) => (Color::Red, "Failure"),
|
Error(..) => (Color::Red, "Error"),
|
||||||
Forward(..) => (Color::Yellow, "Forward"),
|
Forward(..) => (Color::Yellow, "Forward"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,7 +674,7 @@ impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
|
||||||
|
|
||||||
crate::export! {
|
crate::export! {
|
||||||
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
|
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
|
||||||
/// `Failure`.
|
/// `Error` by returning early.
|
||||||
///
|
///
|
||||||
/// # Syntax
|
/// # Syntax
|
||||||
///
|
///
|
||||||
|
@ -691,7 +690,7 @@ crate::export! {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
|
/// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
|
||||||
/// case of a `Forward` or `Failure` variant, the inner type is passed to
|
/// case of a `Forward` or `Error` variant, the inner type is passed to
|
||||||
/// [`From`](std::convert::From), allowing for the conversion between
|
/// [`From`](std::convert::From), allowing for the conversion between
|
||||||
/// specific and more general types. The resulting forward/error is
|
/// specific and more general types. The resulting forward/error is
|
||||||
/// immediately returned. Because of the early return, `try_outcome!` can
|
/// immediately returned. Because of the early return, `try_outcome!` can
|
||||||
|
@ -746,8 +745,8 @@ crate::export! {
|
||||||
macro_rules! try_outcome {
|
macro_rules! try_outcome {
|
||||||
($expr:expr $(,)?) => (match $expr {
|
($expr:expr $(,)?) => (match $expr {
|
||||||
$crate::outcome::Outcome::Success(val) => val,
|
$crate::outcome::Outcome::Success(val) => val,
|
||||||
$crate::outcome::Outcome::Failure(e) => {
|
$crate::outcome::Outcome::Error(e) => {
|
||||||
return $crate::outcome::Outcome::Failure(::std::convert::From::from(e))
|
return $crate::outcome::Outcome::Error(::std::convert::From::from(e))
|
||||||
},
|
},
|
||||||
$crate::outcome::Outcome::Forward(f) => {
|
$crate::outcome::Outcome::Forward(f) => {
|
||||||
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
|
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::convert::Infallible;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
|
||||||
|
@ -12,14 +13,14 @@ use crate::http::uri::{Host, Origin};
|
||||||
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
|
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
|
||||||
|
|
||||||
impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
||||||
type Failure = Status;
|
type Error = Status;
|
||||||
type Forward = Status;
|
type Forward = Status;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_outcome(self, status: Status) -> Outcome<S, E> {
|
fn into_outcome(self, status: Status) -> Outcome<S, E> {
|
||||||
match self {
|
match self {
|
||||||
Ok(val) => Success(val),
|
Ok(val) => Success(val),
|
||||||
Err(err) => Failure((status, err))
|
Err(err) => Error((status, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +86,8 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Request guards always fire in left-to-right declaration order. In the
|
/// Request guards always fire in left-to-right declaration order. In the
|
||||||
/// example above, the order is `a` followed by `b` followed by `c`. Failure is
|
/// example above, the order is `a` followed by `b` followed by `c`. Errors are
|
||||||
/// short-circuiting; if one guard fails, the remaining are not attempted.
|
/// short-circuiting; if one guard errors, the remaining are not attempted.
|
||||||
///
|
///
|
||||||
/// # Outcomes
|
/// # Outcomes
|
||||||
///
|
///
|
||||||
|
@ -99,12 +100,12 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
||||||
/// the value for the corresponding parameter. As long as all other guards
|
/// the value for the corresponding parameter. As long as all other guards
|
||||||
/// succeed, the request will be handled.
|
/// succeed, the request will be handled.
|
||||||
///
|
///
|
||||||
/// * **Failure**(Status, E)
|
/// * **Error**(Status, E)
|
||||||
///
|
///
|
||||||
/// If the `Outcome` is [`Failure`], 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 `Failure`s and retrieve the
|
/// of `Result<S, E>` and `Option<S>` to catch `Error`s and retrieve the
|
||||||
/// error value.
|
/// error value.
|
||||||
///
|
///
|
||||||
/// * **Forward**(Status)
|
/// * **Forward**(Status)
|
||||||
|
@ -191,7 +192,7 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
||||||
///
|
///
|
||||||
/// 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 derivation is a `Success`, the value is
|
/// `FromRequest` implementation. If derivation is a `Success`, the value is
|
||||||
/// returned in `Ok`. If the derivation is a `Failure`, the error value is
|
/// returned in `Ok`. If the derivation is an `Error`, the error value is
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
|
@ -232,9 +233,9 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// match req.headers().get_one("x-api-key") {
|
/// match req.headers().get_one("x-api-key") {
|
||||||
/// None => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
|
/// None => Outcome::Error((Status::BadRequest, ApiKeyError::Missing)),
|
||||||
/// Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)),
|
/// Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)),
|
||||||
/// Some(_) => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
|
/// Some(_) => Outcome::Error((Status::BadRequest, ApiKeyError::Invalid)),
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -390,7 +391,7 @@ pub trait FromRequest<'r>: Sized {
|
||||||
/// Derives an instance of `Self` from the incoming request metadata.
|
/// Derives an instance of `Self` from the incoming request metadata.
|
||||||
///
|
///
|
||||||
/// If the derivation is successful, an outcome of `Success` is returned. If
|
/// If the derivation is successful, an outcome of `Success` is returned. If
|
||||||
/// the derivation fails in an unrecoverable fashion, `Failure` is returned.
|
/// the derivation fails in an unrecoverable fashion, `Error` is returned.
|
||||||
/// `Forward` is returned to indicate that the request should be forwarded
|
/// `Forward` is returned to indicate that the request should be forwarded
|
||||||
/// to other matching routes, if any.
|
/// to other matching routes, if any.
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
|
||||||
|
@ -398,27 +399,27 @@ pub trait FromRequest<'r>: Sized {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for Method {
|
impl<'r> FromRequest<'r> for Method {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
Success(request.method())
|
Success(request.method())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r Origin<'r> {
|
impl<'r> FromRequest<'r> for &'r Origin<'r> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
Success(request.uri())
|
Success(request.uri())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r Host<'r> {
|
impl<'r> FromRequest<'r> for &'r Host<'r> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.host() {
|
match request.host() {
|
||||||
Some(host) => Success(host),
|
Some(host) => Success(host),
|
||||||
None => Forward(Status::NotFound)
|
None => Forward(Status::NotFound)
|
||||||
|
@ -428,9 +429,9 @@ impl<'r> FromRequest<'r> for &'r Host<'r> {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r Route {
|
impl<'r> FromRequest<'r> for &'r Route {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.route() {
|
match request.route() {
|
||||||
Some(route) => Success(route),
|
Some(route) => Success(route),
|
||||||
None => Forward(Status::InternalServerError)
|
None => Forward(Status::InternalServerError)
|
||||||
|
@ -440,18 +441,18 @@ impl<'r> FromRequest<'r> for &'r Route {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r CookieJar<'r> {
|
impl<'r> FromRequest<'r> for &'r CookieJar<'r> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
Success(request.cookies())
|
Success(request.cookies())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r Accept {
|
impl<'r> FromRequest<'r> for &'r Accept {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.accept() {
|
match request.accept() {
|
||||||
Some(accept) => Success(accept),
|
Some(accept) => Success(accept),
|
||||||
None => Forward(Status::NotFound)
|
None => Forward(Status::NotFound)
|
||||||
|
@ -461,9 +462,9 @@ impl<'r> FromRequest<'r> for &'r Accept {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for &'r ContentType {
|
impl<'r> FromRequest<'r> for &'r ContentType {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.content_type() {
|
match request.content_type() {
|
||||||
Some(content_type) => Success(content_type),
|
Some(content_type) => Success(content_type),
|
||||||
None => Forward(Status::NotFound)
|
None => Forward(Status::NotFound)
|
||||||
|
@ -473,9 +474,9 @@ impl<'r> FromRequest<'r> for &'r ContentType {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for IpAddr {
|
impl<'r> FromRequest<'r> for IpAddr {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.client_ip() {
|
match request.client_ip() {
|
||||||
Some(addr) => Success(addr),
|
Some(addr) => Success(addr),
|
||||||
None => Forward(Status::NotFound)
|
None => Forward(Status::NotFound)
|
||||||
|
@ -485,9 +486,9 @@ impl<'r> FromRequest<'r> for IpAddr {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r> FromRequest<'r> for SocketAddr {
|
impl<'r> FromRequest<'r> for SocketAddr {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match request.remote() {
|
match request.remote() {
|
||||||
Some(addr) => Success(addr),
|
Some(addr) => Success(addr),
|
||||||
None => Forward(Status::NotFound)
|
None => Forward(Status::NotFound)
|
||||||
|
@ -497,12 +498,12 @@ impl<'r> FromRequest<'r> for SocketAddr {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
|
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match T::from_request(request).await {
|
match T::from_request(request).await {
|
||||||
Success(val) => Success(Ok(val)),
|
Success(val) => Success(Ok(val)),
|
||||||
Failure((_, e)) => Success(Err(e)),
|
Error((_, e)) => Success(Err(e)),
|
||||||
Forward(status) => Forward(status),
|
Forward(status) => Forward(status),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,21 +511,21 @@ 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 = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
match T::from_request(request).await {
|
match T::from_request(request).await {
|
||||||
Success(val) => Success(Some(val)),
|
Success(val) => Success(Some(val)),
|
||||||
Failure(_) | Forward(_) => Success(None),
|
Error(_) | Forward(_) => Success(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Outcome<T, T::Error> {
|
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Outcome<T, T::Error> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
|
||||||
Success(T::from_request(request).await)
|
Success(T::from_request(request).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ use crate::request::Request;
|
||||||
/// * An `Ok(Response)` indicates success. The `Response` will be written out
|
/// * An `Ok(Response)` indicates success. The `Response` will be written out
|
||||||
/// to the client.
|
/// to the client.
|
||||||
///
|
///
|
||||||
/// * An `Err(Status)` indicates failure. The error catcher for `Status` will
|
/// * An `Err(Status)` indicates an error. The error catcher for `Status` will
|
||||||
/// be invoked to generate a response.
|
/// be invoked to generate a response.
|
||||||
///
|
///
|
||||||
/// # Implementation Tips
|
/// # Implementation Tips
|
||||||
|
|
|
@ -141,7 +141,7 @@ pub trait Handler: Cloneable + Send + Sync + 'static {
|
||||||
/// The variant of `Outcome` returned by the returned `Future` determines
|
/// The variant of `Outcome` returned by the returned `Future` determines
|
||||||
/// what Rocket does next. If the return value is a `Success(Response)`, the
|
/// what Rocket does next. If the return value is a `Success(Response)`, the
|
||||||
/// wrapped `Response` is used to respond to the client. If the return value
|
/// wrapped `Response` is used to respond to the client. If the return value
|
||||||
/// is a `Failure(Status)`, the error catcher for `Status` is invoked to
|
/// is an `Error(Status)`, the error catcher for `Status` is invoked to
|
||||||
/// generate a response. Otherwise, if the return value is `Forward(Data)`,
|
/// generate a response. Otherwise, if the return value is `Forward(Data)`,
|
||||||
/// the next matching route is attempted. If there are no other matching
|
/// the next matching route is attempted. If there are no other matching
|
||||||
/// routes, the `404` error catcher is invoked.
|
/// routes, the `404` error catcher is invoked.
|
||||||
|
@ -172,7 +172,7 @@ impl<'r, 'o: 'r> Outcome<'o> {
|
||||||
/// Return the `Outcome` of response to `req` from `responder`.
|
/// Return the `Outcome` of response to `req` from `responder`.
|
||||||
///
|
///
|
||||||
/// If the responder returns `Ok`, an outcome of `Success` is returned with
|
/// If the responder returns `Ok`, an outcome of `Success` is returned with
|
||||||
/// the response. If the responder returns `Err`, an outcome of `Failure` is
|
/// the response. If the responder returns `Err`, an outcome of `Error` is
|
||||||
/// returned with the status code.
|
/// returned with the status code.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -188,14 +188,14 @@ impl<'r, 'o: 'r> Outcome<'o> {
|
||||||
pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {
|
pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {
|
||||||
match responder.respond_to(req) {
|
match responder.respond_to(req) {
|
||||||
Ok(response) => Outcome::Success(response),
|
Ok(response) => Outcome::Success(response),
|
||||||
Err(status) => Outcome::Failure(status)
|
Err(status) => Outcome::Error(status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `Outcome` of response to `req` from `responder`.
|
/// Return the `Outcome` of response to `req` from `responder`.
|
||||||
///
|
///
|
||||||
/// If the responder returns `Ok`, an outcome of `Success` is returned with
|
/// If the responder returns `Ok`, an outcome of `Success` is returned with
|
||||||
/// the response. If the responder returns `Err`, an outcome of `Failure` is
|
/// the response. If the responder returns `Err`, an outcome of `Error` is
|
||||||
/// returned with the status code.
|
/// returned with the status code.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -214,7 +214,7 @@ impl<'r, 'o: 'r> Outcome<'o> {
|
||||||
let responder = result.map_err(crate::response::Debug);
|
let responder = result.map_err(crate::response::Debug);
|
||||||
match responder.respond_to(req) {
|
match responder.respond_to(req) {
|
||||||
Ok(response) => Outcome::Success(response),
|
Ok(response) => Outcome::Success(response),
|
||||||
Err(status) => Outcome::Failure(status)
|
Err(status) => Outcome::Error(status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +243,8 @@ impl<'r, 'o: 'r> Outcome<'o> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an `Outcome` of `Failure` with the status code `code`. This is
|
/// Return an `Outcome` of `Error` with the status code `code`. This is
|
||||||
/// equivalent to `Outcome::Failure(code)`.
|
/// equivalent to `Outcome::Error(code)`.
|
||||||
///
|
///
|
||||||
/// This method exists to be used during manual routing.
|
/// This method exists to be used during manual routing.
|
||||||
///
|
///
|
||||||
|
@ -255,12 +255,12 @@ impl<'r, 'o: 'r> Outcome<'o> {
|
||||||
/// use rocket::http::Status;
|
/// use rocket::http::Status;
|
||||||
///
|
///
|
||||||
/// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
|
/// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
|
||||||
/// route::Outcome::failure(Status::BadRequest)
|
/// route::Outcome::error(Status::BadRequest)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn failure(code: Status) -> Outcome<'r> {
|
pub fn error(code: Status) -> Outcome<'r> {
|
||||||
Outcome::Failure(code)
|
Outcome::Error(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an `Outcome` of `Forward` with the data `data`. This is
|
/// Return an `Outcome` of `Forward` with the data `data`. This is
|
||||||
|
|
|
@ -76,7 +76,7 @@ use crate::sentinel::Sentry;
|
||||||
/// higher precedence during routing than routes with higher ranks. Thus, routes
|
/// higher precedence during routing than routes with higher ranks. Thus, routes
|
||||||
/// are attempted in ascending rank order. If a higher precedence route returns
|
/// are attempted in ascending rank order. If a higher precedence route returns
|
||||||
/// an `Outcome` of `Forward`, the next highest precedence route is attempted,
|
/// an `Outcome` of `Forward`, the next highest precedence route is attempted,
|
||||||
/// and so on, until a route returns `Success` or `Failure`, or there are no
|
/// and so on, until a route returns `Success` or `Error`, or there are no
|
||||||
/// more routes to try. When all routes have been attempted, Rocket issues a
|
/// more routes to try. When all routes have been attempted, Rocket issues a
|
||||||
/// `404` error, handled by the appropriate [`Catcher`](crate::Catcher).
|
/// `404` error, handled by the appropriate [`Catcher`](crate::Catcher).
|
||||||
///
|
///
|
||||||
|
|
|
@ -201,12 +201,12 @@ impl<'r, T: Deserialize<'r>> FromData<'r> for Json<T> {
|
||||||
match Self::from_data(req, data).await {
|
match Self::from_data(req, data).await {
|
||||||
Ok(value) => Outcome::Success(value),
|
Ok(value) => Outcome::Success(value),
|
||||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
|
Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
|
||||||
Outcome::Failure((Status::PayloadTooLarge, Error::Io(e)))
|
Outcome::Error((Status::PayloadTooLarge, Error::Io(e)))
|
||||||
},
|
},
|
||||||
Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => {
|
Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => {
|
||||||
Outcome::Failure((Status::UnprocessableEntity, Error::Parse(s, e)))
|
Outcome::Error((Status::UnprocessableEntity, Error::Parse(s, e)))
|
||||||
},
|
},
|
||||||
Err(e) => Outcome::Failure((Status::BadRequest, e)),
|
Err(e) => Outcome::Error((Status::BadRequest, e)),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,15 +170,15 @@ impl<'r, T: Deserialize<'r>> FromData<'r> for MsgPack<T> {
|
||||||
match Self::from_data(req, data).await {
|
match Self::from_data(req, data).await {
|
||||||
Ok(value) => Outcome::Success(value),
|
Ok(value) => Outcome::Success(value),
|
||||||
Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
|
Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
|
||||||
Outcome::Failure((Status::PayloadTooLarge, Error::InvalidDataRead(e)))
|
Outcome::Error((Status::PayloadTooLarge, Error::InvalidDataRead(e)))
|
||||||
},
|
},
|
||||||
| Err(e@Error::TypeMismatch(_))
|
| Err(e@Error::TypeMismatch(_))
|
||||||
| Err(e@Error::OutOfRange)
|
| Err(e@Error::OutOfRange)
|
||||||
| Err(e@Error::LengthMismatch(_))
|
| Err(e@Error::LengthMismatch(_))
|
||||||
=> {
|
=> {
|
||||||
Outcome::Failure((Status::UnprocessableEntity, e))
|
Outcome::Error((Status::UnprocessableEntity, e))
|
||||||
},
|
},
|
||||||
Err(e) => Outcome::Failure((Status::BadRequest, e)),
|
Err(e) => Outcome::Error((Status::BadRequest, e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
use crate::request::FromParam;
|
use crate::request::FromParam;
|
||||||
use crate::form::{self, FromFormField, ValueField};
|
use crate::form::{self, FromFormField, ValueField};
|
||||||
|
|
||||||
/// Error returned on [`FromParam`] or [`FromFormField`] failure.
|
/// Error returned on [`FromParam`] or [`FromFormField`] failures.
|
||||||
///
|
///
|
||||||
pub use uuid_::Error;
|
pub use uuid_::Error;
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ async fn hyper_service_fn(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rocket<Orbit> {
|
impl Rocket<Orbit> {
|
||||||
/// Wrapper around `_send_response` to log a success or failure.
|
/// Wrapper around `_send_response` to log a success or error.
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn send_response(
|
async fn send_response(
|
||||||
&self,
|
&self,
|
||||||
|
@ -290,12 +290,12 @@ impl Rocket<Orbit> {
|
||||||
request._set_method(Method::Get);
|
request._set_method(Method::Get);
|
||||||
match self.route(request, data).await {
|
match self.route(request, data).await {
|
||||||
Outcome::Success(response) => response,
|
Outcome::Success(response) => response,
|
||||||
Outcome::Failure(status) => self.handle_error(status, request).await,
|
Outcome::Error(status) => self.handle_error(status, request).await,
|
||||||
Outcome::Forward((_, status)) => self.handle_error(status, request).await,
|
Outcome::Forward((_, status)) => self.handle_error(status, request).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Forward((_, status)) => self.handle_error(status, request).await,
|
Outcome::Forward((_, status)) => self.handle_error(status, request).await,
|
||||||
Outcome::Failure(status) => self.handle_error(status, request).await,
|
Outcome::Error(status) => self.handle_error(status, request).await,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the cookies. Note that error responses will only include cookies
|
// Set the cookies. Note that error responses will only include cookies
|
||||||
|
@ -310,7 +310,7 @@ impl Rocket<Orbit> {
|
||||||
|
|
||||||
/// Tries to find a `Responder` for a given `request`. It does this by
|
/// Tries to find a `Responder` for a given `request`. It does this by
|
||||||
/// routing the request and calling the handler for each matching route
|
/// routing the request and calling the handler for each matching route
|
||||||
/// until one of the handlers returns success or failure, or there are no
|
/// until one of the handlers returns success or error, or there are no
|
||||||
/// additional routes to try (forward). The corresponding outcome for each
|
/// additional routes to try (forward). The corresponding outcome for each
|
||||||
/// condition is returned.
|
/// condition is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -329,14 +329,14 @@ impl Rocket<Orbit> {
|
||||||
|
|
||||||
let name = route.name.as_deref();
|
let name = route.name.as_deref();
|
||||||
let outcome = handle(name, || route.handler.handle(request, data)).await
|
let outcome = handle(name, || route.handler.handle(request, data)).await
|
||||||
.unwrap_or(Outcome::Failure(Status::InternalServerError));
|
.unwrap_or(Outcome::Error(Status::InternalServerError));
|
||||||
|
|
||||||
// Check if the request processing completed (Some) or if the
|
// Check if the request processing completed (Some) or if the
|
||||||
// request needs to be forwarded. If it does, continue the loop
|
// request needs to be forwarded. If it does, continue the loop
|
||||||
// (None) to try again.
|
// (None) to try again.
|
||||||
info_!("{} {}", "Outcome:".primary().bold(), outcome);
|
info_!("{} {}", "Outcome:".primary().bold(), outcome);
|
||||||
match outcome {
|
match outcome {
|
||||||
o@Outcome::Success(_) | o@Outcome::Failure(_) => return o,
|
o@Outcome::Success(_) | o@Outcome::Error(_) => return o,
|
||||||
Outcome::Forward(forwarded) => (data, status) = forwarded,
|
Outcome::Forward(forwarded) => (data, status) = forwarded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ impl Rocket<Orbit> {
|
||||||
|
|
||||||
// Invokes the catcher for `status`. Returns the response on success.
|
// Invokes the catcher for `status`. Returns the response on success.
|
||||||
//
|
//
|
||||||
// On catcher failure, the 500 error catcher is attempted. If _that_ fails,
|
// On catcher error, the 500 error catcher is attempted. If _that_ errors,
|
||||||
// the (infallible) default 500 error cather is used.
|
// the (infallible) default 500 error cather is used.
|
||||||
pub(crate) async fn handle_error<'s, 'r: 's>(
|
pub(crate) async fn handle_error<'s, 'r: 's>(
|
||||||
&'s self,
|
&'s self,
|
||||||
|
|
|
@ -202,7 +202,7 @@ impl<'r, T: Send + Sync + 'static> FromRequest<'r> for &'r State<T> {
|
||||||
Some(state) => Outcome::Success(state),
|
Some(state) => Outcome::Success(state),
|
||||||
None => {
|
None => {
|
||||||
error_!("Attempted to retrieve unmanaged state `{}`!", type_name::<T>());
|
error_!("Attempted to retrieve unmanaged state `{}`!", type_name::<T>());
|
||||||
Outcome::Failure((Status::InternalServerError, ()))
|
Outcome::Error((Status::InternalServerError, ()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
if !req.content_type().map_or(false, |ct| ct.is_plain()) {
|
if !req.content_type().map_or(false, |ct| ct.is_plain()) {
|
||||||
println!(" => Content-Type of upload must be text/plain. Ignoring.");
|
println!(" => Content-Type of upload must be text/plain. Ignoring.");
|
||||||
return route::Outcome::failure(Status::BadRequest);
|
return route::Outcome::error(Status::BadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = req.rocket().config().temp_dir.relative().join("upload.txt");
|
let path = req.rocket().config().temp_dir.relative().join("upload.txt");
|
||||||
|
@ -49,10 +49,10 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(" => Failed copying.");
|
println!(" => Failed copying.");
|
||||||
route::Outcome::failure(Status::InternalServerError)
|
route::Outcome::error(Status::InternalServerError)
|
||||||
} else {
|
} else {
|
||||||
println!(" => Couldn't open file: {:?}", file.unwrap_err());
|
println!(" => Couldn't open file: {:?}", file.unwrap_err());
|
||||||
route::Outcome::failure(Status::InternalServerError)
|
route::Outcome::error(Status::InternalServerError)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,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 failure.
|
you can use an `Option` or `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
|
||||||
|
@ -353,7 +353,7 @@ fn index(param: isize, a: A, b: B, c: C) { /* ... */ }
|
||||||
```
|
```
|
||||||
|
|
||||||
Request guards always fire in left-to-right declaration order. In the example
|
Request guards always fire in left-to-right declaration order. In the example
|
||||||
above, the order will be `A` followed by `B` followed by `C`. Failure is
|
above, the order will be `A` followed by `B` followed by `C`. Errors are
|
||||||
short-circuiting; if one guard fails, the remaining are not attempted. To learn
|
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.
|
||||||
|
@ -484,7 +484,7 @@ The three routes above encode authentication _and_ authorization. The
|
||||||
the admin panel displayed. If the user is not an admin, the `AdminUser` guard
|
the admin panel displayed. If the user is not an admin, the `AdminUser` guard
|
||||||
will forward. Since the `admin_panel_user` route is ranked next highest, it is
|
will forward. Since the `admin_panel_user` route is ranked next highest, it is
|
||||||
attempted next. This route succeeds if there is _any_ user signed in, and an
|
attempted next. This route succeeds if there is _any_ user signed in, and an
|
||||||
authorization failure message is displayed. Finally, if a user isn't signed in,
|
authorization error message is displayed. Finally, if a user isn't signed in,
|
||||||
the `admin_panel_redirect` route is attempted. Since this route has no guards,
|
the `admin_panel_redirect` route is attempted. Since this route has no guards,
|
||||||
it always succeeds. The user is redirected to a log in page.
|
it always succeeds. The user is redirected to a log in page.
|
||||||
|
|
||||||
|
@ -522,7 +522,7 @@ If the `User` guard forwards or fails, 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
|
||||||
retrieving the error type `E` on failure. As an example, when the
|
retrieving the error type `E` on error. As an example, when the
|
||||||
[`mtls::Certificate`] type fails, it reports the reason in an [`mtls::Error`]
|
[`mtls::Certificate`] type fails, it reports the reason in an [`mtls::Error`]
|
||||||
type. The value can be retrieved in a handler by using a `Result<Certificate,
|
type. The value can be retrieved in a handler by using a `Result<Certificate,
|
||||||
Error>` guard:
|
Error>` guard:
|
||||||
|
@ -876,7 +876,7 @@ fields implement [`FromForm`], or equivalently, [`FromFormField`].
|
||||||
If a `POST /todo` request arrives, the form data will automatically be parsed
|
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 failure 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 `Option` and `Result` types:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
|
@ -289,7 +289,7 @@ fn handler() -> &'static str {
|
||||||
|
|
||||||
`Option` is a _wrapping_ responder: an `Option<T>` can only be returned when `T`
|
`Option` is a _wrapping_ responder: an `Option<T>` can only be returned when `T`
|
||||||
implements `Responder`. If the `Option` is `Some`, the wrapped responder is used
|
implements `Responder`. If the `Option` is `Some`, the wrapped responder is used
|
||||||
to respond to the client. Otherwise, a error of **404 - Not Found** is returned
|
to respond to the client. Otherwise, an error of **404 - Not Found** is returned
|
||||||
to the client.
|
to the client.
|
||||||
|
|
||||||
This implementation makes `Option` a convenient type to return when it is not
|
This implementation makes `Option` a convenient type to return when it is not
|
||||||
|
|
|
@ -26,7 +26,7 @@ macro_rules! assert_form_parses {
|
||||||
Ok(v) => assert_eq!(v, $value, "{}", $form),
|
Ok(v) => assert_eq!(v, $value, "{}", $form),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e);
|
eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e);
|
||||||
panic!("form parse failure");
|
panic!("form parse error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue