Remove second lifetime from 'FromRequest'.

While offering some utility, the lifetime did not carry its weight, and
in practice offered no further ability to borrow. This greatly
simplifies request guard implementations.
This commit is contained in:
Sergio Benitez 2021-03-14 19:57:59 -07:00
parent 2366bff05f
commit 70b42e6f0e
23 changed files with 170 additions and 175 deletions

View File

@ -47,10 +47,10 @@ fn parse_invocation(attr: TokenStream, input: TokenStream) -> Result<DatabaseInv
};
Ok(DatabaseInvocation {
structure,
type_name: input.ident,
visibility: input.vis,
db_name: string_lit.value(),
structure: structure,
connection_type: inner_type,
})
}
@ -109,10 +109,10 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result<TokenStrea
}
#[::rocket::async_trait]
impl<'a, 'r> #request::FromRequest<'a, 'r> for #guard_type {
impl<'r> #request::FromRequest<'r> for #guard_type {
type Error = ();
async fn from_request(__r: &'a #request::Request<'r>) -> #request::Outcome<Self, ()> {
async fn from_request(__r: &'r #request::Request<'_>) -> #request::Outcome<Self, ()> {
<#conn>::from_request(__r).await.map(Self)
}
}

View File

@ -4,7 +4,7 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
7 | struct A(Unknown);
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
::: $WORKSPACE/contrib/lib/src/databases.rs
::: $WORKSPACE/contrib/lib/src/databases/connection.rs
|
| pub struct Connection<K, C: Poolable> {
| -------- required by this bound in `rocket_contrib::databases::Connection`
@ -15,7 +15,7 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
10 | struct B(Vec<i32>);
| ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
::: $WORKSPACE/contrib/lib/src/databases.rs
::: $WORKSPACE/contrib/lib/src/databases/connection.rs
|
| pub struct Connection<K, C: Poolable> {
| -------- required by this bound in `rocket_contrib::databases::Connection`

View File

@ -4,7 +4,7 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
7 | struct A(Unknown);
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
::: $WORKSPACE/contrib/lib/src/databases.rs
::: $WORKSPACE/contrib/lib/src/databases/connection.rs
|
| pub struct Connection<K, C: Poolable> {
| -------- required by this bound in `rocket_contrib::databases::Connection`
@ -15,7 +15,7 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
10 | struct B(Vec<i32>);
| ^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
::: $WORKSPACE/contrib/lib/src/databases.rs
::: $WORKSPACE/contrib/lib/src/databases/connection.rs
|
| pub struct Connection<K, C: Poolable> {
| -------- required by this bound in `rocket_contrib::databases::Connection`

View File

@ -172,11 +172,11 @@ impl<K, C: Poolable> Drop for ConnectionPool<K, C> {
}
#[rocket::async_trait]
impl<'a, 'r, K: 'static, C: Poolable> FromRequest<'a, 'r> for Connection<K, C> {
impl<'r, K: 'static, C: Poolable> FromRequest<'r> for Connection<K, C> {
type Error = ();
#[inline]
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, ()> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> {
match request.managed_state::<ConnectionPool<K, C>>() {
Some(c) => c.get().await.into_outcome(Status::ServiceUnavailable),
None => {

View File

@ -85,10 +85,10 @@ impl Metadata<'_> {
/// an error is printed and an empty `Err` with status `InternalServerError`
/// (`500`) is returned.
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Metadata<'a> {
impl<'r> FromRequest<'r> for Metadata<'r> {
type Error = ();
async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
request.guard::<State<'_, ContextManager>>().await
.succeeded()
.and_then(|cm| Some(request::Outcome::Success(Metadata(cm.inner()))))

View File

@ -41,15 +41,15 @@ error[E0277]: the trait bound `Q: FromData<'_>` is not satisfied
| async fn from_data(req: &'r Request<'_>, data: Data) -> Outcome<Self, Self::Error>;
| -- required by this bound in `rocket::data::FromData::from_data`
error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied
error[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied
--> $DIR/route-type-errors.rs:21:10
|
21 | fn f5(a: Q, foo: Q) {}
| ^ the trait `FromRequest<'_, '_>` is not implemented for `Q`
| ^ the trait `FromRequest<'_>` is not implemented for `Q`
|
::: $WORKSPACE/core/lib/src/request/from_request.rs
|
| pub trait FromRequest<'a, 'r>: Sized {
| async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
| -- required by this bound in `from_request`
error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied
@ -60,15 +60,15 @@ error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied
|
= note: required by `from_param`
error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied
error[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied
--> $DIR/route-type-errors.rs:24:10
|
24 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {}
| ^ the trait `FromRequest<'_, '_>` is not implemented for `Q`
| ^ the trait `FromRequest<'_>` is not implemented for `Q`
|
::: $WORKSPACE/core/lib/src/request/from_request.rs
|
| pub trait FromRequest<'a, 'r>: Sized {
| async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
| -- required by this bound in `from_request`
error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied

View File

@ -41,15 +41,15 @@ error[E0277]: the trait bound `Q: FromData<'_>` is not satisfied
| async fn from_data(req: &'r Request<'_>, data: Data) -> Outcome<Self, Self::Error>;
| -- required by this bound in `rocket::data::FromData::from_data`
error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied
error[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied
--> $DIR/route-type-errors.rs:21:10
|
21 | fn f5(a: Q, foo: Q) {}
| ^ the trait `FromRequest<'_, '_>` is not implemented for `Q`
| ^ the trait `FromRequest<'_>` is not implemented for `Q`
|
::: $WORKSPACE/core/lib/src/request/from_request.rs
|
| pub trait FromRequest<'a, 'r>: Sized {
| async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
| -- required by this bound in `from_request`
error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied
@ -60,15 +60,15 @@ error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied
|
= note: required by `from_param`
error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied
error[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied
--> $DIR/route-type-errors.rs:24:10
|
24 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {}
| ^ the trait `FromRequest<'_, '_>` is not implemented for `Q`
| ^ the trait `FromRequest<'_>` is not implemented for `Q`
|
::: $WORKSPACE/core/lib/src/request/from_request.rs
|
| pub trait FromRequest<'a, 'r>: Sized {
| async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
| -- required by this bound in `from_request`
error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied

View File

@ -380,10 +380,10 @@ impl Provider for Config {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'r Config {
impl<'r> FromRequest<'r> for &'r Config {
type Error = std::convert::Infallible;
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
request::Outcome::Success(req.config())
}
}

View File

@ -182,10 +182,10 @@ impl PartialEq for SecretKey {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a SecretKey {
impl<'r> FromRequest<'r> for &'r SecretKey {
type Error = std::convert::Infallible;
async fn from_request(req: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Outcome::Success(&req.state.config.secret_key)
}
}

View File

@ -111,10 +111,10 @@ pub use self::cookie::{Cookie, SameSite, Iter};
/// struct User(usize);
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for User {
/// impl<'r> FromRequest<'r> for User {
/// type Error = std::convert::Infallible;
///
/// async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
/// request.cookies()
/// .get_private("user_id")
/// .and_then(|c| c.value().parse().ok())

View File

@ -300,10 +300,10 @@ impl fmt::Display for Limits {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'r Limits {
impl<'r> FromRequest<'r> for &'r Limits {
type Error = std::convert::Infallible;
async fn from_request(req: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Outcome::Success(req.limits())
}
}

View File

@ -353,10 +353,10 @@ pub use self::info_kind::{Info, Kind};
///
/// // Allows a route to access the time a request was initiated.
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for StartTime {
/// impl<'r> FromRequest<'r> for StartTime {
/// type Error = ();
///
/// async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
/// match *request.local_cache(|| TimerStart(None)) {
/// TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),
/// TimerStart(None) => request::Outcome::Failure((Status::InternalServerError, ())),

View File

@ -645,10 +645,10 @@ impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
/// struct Guard2;
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for Guard1 {
/// impl<'r> FromRequest<'r> for Guard1 {
/// type Error = ();
///
/// async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
/// // Attempt to fetch the guard, passing through any error or forward.
/// let atomics = try_outcome!(req.guard::<State<'_, Atomics>>().await);
/// atomics.uncached.fetch_add(1, Ordering::Relaxed);
@ -659,10 +659,10 @@ impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
/// }
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for Guard2 {
/// impl<'r> FromRequest<'r> for Guard2 {
/// type Error = ();
///
/// async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
/// // Attempt to fetch the guard, passing through any error or forward.
/// let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);
/// Success(Guard2)

View File

@ -1,8 +1,6 @@
use std::fmt::Debug;
use std::net::{IpAddr, SocketAddr};
use futures::future::BoxFuture;
use crate::router::Route;
use crate::request::Request;
use crate::outcome::{self, IntoOutcome};
@ -60,10 +58,10 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # type MyError = String;
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for MyType {
/// impl<'r> FromRequest<'r> for MyType {
/// type Error = MyError;
///
/// async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
/// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
/// /* .. */
/// # unimplemented!()
/// }
@ -203,42 +201,36 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// use rocket::http::Status;
/// use rocket::request::{self, Outcome, Request, FromRequest};
///
/// struct ApiKey(String);
///
/// /// Returns true if `key` is a valid API key string.
/// fn is_valid(key: &str) -> bool {
/// key == "valid_api_key"
/// }
/// struct ApiKey<'r>(&'r str);
///
/// #[derive(Debug)]
/// enum ApiKeyError {
/// BadCount,
/// Missing,
/// Invalid,
/// }
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for ApiKey {
/// impl<'r> FromRequest<'r> for ApiKey<'r> {
/// type Error = ApiKeyError;
///
/// async fn from_request(req: &'a Request<'r>) -> Outcome<Self, Self::Error> {
/// let keys: Vec<_> = req.headers().get("x-api-key").collect();
/// match keys.len() {
/// 0 => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
/// 1 if is_valid(keys[0]) => Outcome::Success(ApiKey(keys[0].to_string())),
/// 1 => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
/// _ => Outcome::Failure((Status::BadRequest, ApiKeyError::BadCount)),
/// async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
/// /// Returns true if `key` is a valid API key string.
/// fn is_valid(key: &str) -> bool {
/// key == "valid_api_key"
/// }
///
/// match req.headers().get_one("x-api-key") {
/// None => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
/// Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)),
/// Some(_) => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
/// }
/// }
/// }
///
/// #[get("/sensitive")]
/// fn sensitive(key: ApiKey) -> &'static str {
/// # let _key = key;
/// fn sensitive(key: ApiKey<'_>) -> &'static str {
/// "Sensitive data."
/// }
///
/// # fn main() { }
/// ```
///
/// # Request-Local State
@ -264,9 +256,9 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # }
/// # }
/// # #[rocket::async_trait]
/// # impl<'a, 'r> FromRequest<'a, 'r> for Database {
/// # impl<'r> FromRequest<'r> for Database {
/// # type Error = ();
/// # async fn from_request(request: &'a Request<'r>) -> Outcome<Database, ()> {
/// # async fn from_request(request: &'r Request<'_>) -> Outcome<Database, ()> {
/// # Outcome::Success(Database)
/// # }
/// # }
@ -274,10 +266,10 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # struct Admin { user: User }
/// #
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for User {
/// impl<'r> FromRequest<'r> for User {
/// type Error = ();
///
/// async fn from_request(request: &'a Request<'r>) -> Outcome<User, ()> {
/// async fn from_request(request: &'r Request<'_>) -> Outcome<User, ()> {
/// let db = try_outcome!(request.guard::<Database>().await);
/// request.cookies()
/// .get_private("user_id")
@ -288,10 +280,10 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// }
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for Admin {
/// impl<'r> FromRequest<'r> for Admin {
/// type Error = ();
///
/// async fn from_request(request: &'a Request<'r>) -> Outcome<Admin, ()> {
/// async fn from_request(request: &'r Request<'_>) -> Outcome<Admin, ()> {
/// // This will unconditionally query the database!
/// let user = try_outcome!(request.guard::<User>().await);
/// if user.is_admin {
@ -328,9 +320,9 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # }
/// # }
/// # #[rocket::async_trait]
/// # impl<'a, 'r> FromRequest<'a, 'r> for Database {
/// # impl<'r> FromRequest<'r> for Database {
/// # type Error = ();
/// # async fn from_request(request: &'a Request<'r>) -> Outcome<Database, ()> {
/// # async fn from_request(request: &'r Request<'_>) -> Outcome<Database, ()> {
/// # Outcome::Success(Database)
/// # }
/// # }
@ -338,10 +330,10 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # struct Admin<'a> { user: &'a User }
/// #
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for &'a User {
/// impl<'r> FromRequest<'r> for &'r User {
/// type Error = std::convert::Infallible;
///
/// async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
/// async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
/// // This closure will execute at most once per request, regardless of
/// // the number of times the `User` guard is executed.
/// let user_result = request.local_cache_async(async {
@ -357,10 +349,10 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// }
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for Admin<'a> {
/// impl<'r> FromRequest<'r> for Admin<'r> {
/// type Error = std::convert::Infallible;
///
/// async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
/// async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
/// let user = try_outcome!(request.guard::<&User>().await);
/// if user.is_admin {
/// Outcome::Success(Admin { user })
@ -377,7 +369,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
///
/// [request-local state]: https://rocket.rs/master/guide/state/#request-local-state
#[crate::async_trait]
pub trait FromRequest<'a, 'r>: Sized {
pub trait FromRequest<'r>: Sized {
/// The associated error to be returned if derivation fails.
type Error: Debug;
@ -387,32 +379,32 @@ pub trait FromRequest<'a, 'r>: Sized {
/// the derivation fails in an unrecoverable fashion, `Failure` is returned.
/// `Forward` is returned to indicate that the request should be forwarded
/// to other matching routes, if any.
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error>;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Method {
impl<'r> FromRequest<'r> for Method {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Success(request.method())
}
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a Origin<'a> {
impl<'r> FromRequest<'r> for &'r Origin<'r> {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Success(request.uri())
}
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'r Route {
impl<'r> FromRequest<'r> for &'r Route {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match request.route() {
Some(route) => Success(route),
None => Forward(())
@ -421,19 +413,19 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'r Route {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a CookieJar<'r> {
impl<'r> FromRequest<'r> for &'r CookieJar<'r> {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Success(request.cookies())
}
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a Accept {
impl<'r> FromRequest<'r> for &'r Accept {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match request.accept() {
Some(accept) => Success(accept),
None => Forward(())
@ -442,10 +434,10 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a Accept {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a ContentType {
impl<'r> FromRequest<'r> for &'r ContentType {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match request.content_type() {
Some(content_type) => Success(content_type),
None => Forward(())
@ -454,10 +446,10 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a ContentType {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for IpAddr {
impl<'r> FromRequest<'r> for IpAddr {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match request.client_ip() {
Some(addr) => Success(addr),
None => Forward(())
@ -466,10 +458,10 @@ impl<'a, 'r> FromRequest<'a, 'r> for IpAddr {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for SocketAddr {
impl<'r> FromRequest<'r> for SocketAddr {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match request.remote() {
Some(addr) => Success(addr),
None => Forward(())
@ -477,33 +469,27 @@ impl<'a, 'r> FromRequest<'a, 'r> for SocketAddr {
}
}
impl<'a, 'r, T: FromRequest<'a, 'r> + 'a> FromRequest<'a, 'r> for Result<T, T::Error> {
#[crate::async_trait]
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
type Error = std::convert::Infallible;
fn from_request<'y>(request: &'a Request<'r>) -> BoxFuture<'y, Outcome<Self, Self::Error>>
where 'a: 'y, 'r: 'y
{
// TODO: FutureExt::map is a workaround (see rust-lang/rust#60658)
use futures::future::FutureExt;
T::from_request(request).map(|x| match x {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match T::from_request(request).await {
Success(val) => Success(Ok(val)),
Failure((_, e)) => Success(Err(e)),
Forward(_) => Forward(()),
}).boxed()
}
}
}
impl<'a, 'r, T: FromRequest<'a, 'r> + 'a> FromRequest<'a, 'r> for Option<T> {
#[crate::async_trait]
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {
type Error = std::convert::Infallible;
fn from_request<'y>(request: &'a Request<'r>) -> BoxFuture<'y, Outcome<Self, Self::Error>>
where 'a: 'y, 'r: 'y
{
// TODO: FutureExt::map is a workaround (see rust-lang/rust#60658)
use futures::future::FutureExt;
T::from_request(request).map(|x| match x {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match T::from_request(request).await {
Success(val) => Success(Some(val)),
Failure(_) | Forward(_) => Success(None),
}).boxed()
}
}
}

View File

@ -531,7 +531,7 @@ impl<'r> Request<'r> {
/// # })
/// ```
pub fn guard<'z, 'a, T>(&'a self) -> BoxFuture<'z, Outcome<T, T::Error>>
where T: FromRequest<'a, 'r> + 'z, 'a: 'z, 'r: 'z
where T: FromRequest<'a> + 'z, 'a: 'z, 'r: 'z
{
T::from_request(self)
}

View File

@ -237,10 +237,10 @@ impl<'a> FlashMessage<'a> {
/// The suggested use is through an `Option` and the `FlashMessage` type alias
/// in `request`: `Option<FlashMessage>`.
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for FlashMessage<'a> {
impl<'r> FromRequest<'r> for FlashMessage<'r> {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
trace_!("Flash: attempting to retrieve message.");
req.cookies().get(FLASH_COOKIE_NAME).ok_or(()).and_then(|cookie| {
trace_!("Flash: retrieving message: {:?}", cookie);

View File

@ -50,11 +50,11 @@ impl Shutdown {
}
#[crate::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Shutdown {
impl<'r> FromRequest<'r> for Shutdown {
type Error = std::convert::Infallible;
#[inline]
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
Outcome::Success(request.state.shutdown.clone())
}
}

View File

@ -53,24 +53,33 @@ use crate::http::Status;
/// # Within Request Guards
///
/// Because `State` is itself a request guard, managed state can be retrieved
/// from another request guard's implementation. In the following code example,
/// `Item` retrieves the `MyConfig` managed state in its [`FromRequest`]
/// implementation using the [`Request::guard()`] method.
/// from another request guard's implementation using either
/// [`Request::guard()`] or [`Request::managed_state()`]. In the following code
/// example, the `Item` request guard retrieves `MyConfig` from managed state:
///
/// ```rust
/// use rocket::State;
/// use rocket::request::{self, Request, FromRequest};
/// use rocket::outcome::IntoOutcome;
///
/// # struct MyConfig{ user_val: String };
/// struct Item(String);
/// struct Item<'r>(&'r str);
///
/// #[rocket::async_trait]
/// impl<'a, 'r> FromRequest<'a, 'r> for Item {
/// impl<'r> FromRequest<'r> for Item<'r> {
/// type Error = ();
///
/// async fn from_request(request: &'a Request<'r>) -> request::Outcome<Item, ()> {
/// request.guard::<State<MyConfig>>().await
/// .map(|my_config| Item(my_config.user_val.clone()))
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
/// // Using `State` as a request guard. Use `inner()` to get an `'r`.
/// let outcome = request.guard::<State<MyConfig>>().await
/// .map(|my_config| Item(&my_config.inner().user_val));
///
/// // Or alternatively, using `Request::managed_state()`:
/// let outcome = request.managed_state::<MyConfig>()
/// .map(|my_config| Item(&my_config.user_val))
/// .or_forward(());
///
/// outcome
/// }
/// }
/// ```
@ -160,11 +169,11 @@ impl<'r, T: Send + Sync + 'static> State<'r, T> {
}
#[crate::async_trait]
impl<'a, 'r, T: Send + Sync + 'static> FromRequest<'a, 'r> for State<'r, T> {
impl<'r, T: Send + Sync + 'static> FromRequest<'r> for State<'r, T> {
type Error = ();
#[inline(always)]
async fn from_request(req: &'a Request<'r>) -> request::Outcome<State<'r, T>, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
match req.state.managed.try_get::<T>() {
Some(state) => Outcome::Success(State(state)),
None => {

View File

@ -7,10 +7,10 @@ use rocket::outcome::IntoOutcome;
struct HasContentType;
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for HasContentType {
impl<'r> FromRequest<'r> for HasContentType {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
req.content_type().map(|_| HasContentType).or_forward(())
}
}

View File

@ -7,10 +7,10 @@ use rocket::outcome::Outcome::*;
struct HeaderCount(usize);
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for HeaderCount {
impl<'r> FromRequest<'r> for HeaderCount {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
Success(HeaderCount(request.headers().len()))
}
}

View File

@ -20,10 +20,10 @@ struct Guard3;
struct Guard4;
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Guard1 {
impl<'r> FromRequest<'r> for Guard1 {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
let atomics = try_outcome!(req.guard::<State<'_, Atomics>>().await);
atomics.uncached.fetch_add(1, Ordering::Relaxed);
req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
@ -33,20 +33,20 @@ impl<'a, 'r> FromRequest<'a, 'r> for Guard1 {
}
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Guard2 {
impl<'r> FromRequest<'r> for Guard2 {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
try_outcome!(req.guard::<Guard1>().await);
Outcome::Success(Guard2)
}
}
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Guard3 {
impl<'r> FromRequest<'r> for Guard3 {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
let atomics = try_outcome!(req.guard::<State<'_, Atomics>>().await);
atomics.uncached.fetch_add(1, Ordering::Relaxed);
req.local_cache_async(async {
@ -58,10 +58,10 @@ impl<'a, 'r> FromRequest<'a, 'r> for Guard3 {
}
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Guard4 {
impl<'r> FromRequest<'r> for Guard4 {
type Error = ();
async fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
try_outcome!(Guard3::from_request(req).await);
Outcome::Success(Guard4)
}

View File

@ -22,10 +22,10 @@ struct Login {
struct User(usize);
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for User {
impl<'r> FromRequest<'r> for User {
type Error = std::convert::Infallible;
async fn from_request(request: &'a Request<'r>) -> request::Outcome<User, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> request::Outcome<User, Self::Error> {
request.cookies()
.get_private("user_id")
.and_then(|cookie| cookie.value().parse().ok())

View File

@ -128,10 +128,10 @@ use rocket::request::{self, Request, FromRequest};
# struct HitCount { count: AtomicUsize }
# type ErrorType = ();
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for T {
impl<'r> FromRequest<'r> for T {
type Error = ErrorType;
async fn from_request(req: &'a Request<'r>) -> request::Outcome<T, Self::Error> {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<T, Self::Error> {
let hit_count_state = try_outcome!(req.guard::<State<HitCount>>().await);
let current_count = hit_count_state.count.load(Ordering::Relaxed);
/* ... */
@ -173,10 +173,10 @@ struct RequestId(pub usize);
/// Returns the current request's ID, assigning one only as necessary.
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for &'a RequestId {
impl<'r> FromRequest<'r> for &'r RequestId {
type Error = ();
async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
// The closure passed to `local_cache` will be executed at most once per
// request: the first time the `RequestId` guard is used. If it is
// requested again, `local_cache` will return the same value.