Take '&mut Data' in 'on_request' fairings.

Resolves #1438.
This commit is contained in:
Sergio Benitez 2020-10-20 20:22:32 -07:00
parent 1fb061496d
commit 7337321efb
10 changed files with 76 additions and 59 deletions

View File

@ -126,23 +126,11 @@ pub struct TemplateFairing {
#[rocket::async_trait]
impl Fairing for TemplateFairing {
fn info(&self) -> Info {
// The on_request part of this fairing only applies in debug
// mode, so only register it in debug mode.
#[cfg(debug_assertions)]
let info = Info {
name: "Templates",
kind: Kind::Attach | Kind::Request,
};
// on_request only applies in debug mode, so only enable it in debug.
#[cfg(debug_assertions)] let kind = Kind::Attach | Kind::Request;
#[cfg(not(debug_assertions))] let kind = Kind::Attach;
// FIXME: We declare two `info` variables here, instead of just one with
// `cfg`s on `kind`, due to issue #63 in `async_trait`.
#[cfg(not(debug_assertions))]
let info = Info {
name: "Templates",
kind: Kind::Attach,
};
info
Info { kind, name: "Templates" }
}
/// Initializes the template context. Templates will be searched for in the
@ -184,7 +172,7 @@ impl Fairing for TemplateFairing {
}
#[cfg(debug_assertions)]
async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &rocket::Data) {
async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &mut rocket::Data) {
let cm = req.guard::<rocket::State<'_, ContextManager>>().await
.expect("Template ContextManager registered in on_attach");

View File

@ -102,10 +102,12 @@ impl Data {
/// method can be used to determine if this buffer contains _all_ of the
/// data in the body of the request.
///
/// # Example
/// # Examples
///
/// In a data guard:
///
/// ```rust
/// use rocket::request::Request;
/// use rocket::request::{self, Request, FromRequest};
/// use rocket::data::{self, Data, FromData};
/// # struct MyType;
/// # type MyError = String;
@ -115,7 +117,7 @@ impl Data {
/// type Error = MyError;
///
/// async fn from_data(req: &Request<'_>, mut data: Data) -> data::Outcome<Self, MyError> {
/// if data.peek(10).await != b"hi" {
/// if data.peek(2).await != b"hi" {
/// return data::Outcome::Forward(data)
/// }
///
@ -124,6 +126,33 @@ impl Data {
/// }
/// }
/// ```
///
/// In a fairing:
///
/// ```
/// use rocket::{Cargo, Rocket, Request, Data, Response};
/// use rocket::fairing::{Fairing, Info, Kind};
/// # struct MyType;
///
/// #[rocket::async_trait]
/// impl Fairing for MyType {
/// fn info(&self) -> Info {
/// Info {
/// name: "Data Peeker",
/// kind: Kind::Request
/// }
/// }
///
/// async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {
/// if data.peek(2).await == b"hi" {
/// /* do something; body data starts with `"hi"` */
/// }
///
/// /* .. */
/// # unimplemented!()
/// }
/// }
/// ```
pub async fn peek(&mut self, num: usize) -> &[u8] {
let num = std::cmp::min(PEEK_BYTES, num);
let mut len = self.buffer.len();

View File

@ -209,12 +209,12 @@ pub type FromDataFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
/// Parse
/// }
///
/// impl<'a> FromTransformedData<'a> for Name<'a> {
/// impl<'r> FromTransformedData<'r> for Name<'r> {
/// type Error = NameError;
/// type Owned = String;
/// type Borrowed = str;
///
/// fn transform<'r>(_: &'r Request, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
/// fn transform(_: &'r Request, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
/// Box::pin(async move {
/// let outcome = match data.open(NAME_LIMIT).stream_to_string().await {
/// Ok(string) => Outcome::Success(string),
@ -226,7 +226,7 @@ pub type FromDataFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
/// })
/// }
///
/// fn from_data(_: &'a Request, outcome: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error> {
/// fn from_data(_: &'r Request, outcome: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
/// Box::pin(async move {
/// // Retrieve a borrow to the now transformed `String` (an &str).
/// // This is only correct because we know we _always_ return a
@ -332,7 +332,7 @@ pub type FromDataFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
///
/// For an example of a type that wouldn't require transformation, see the
/// [`FromData`] documentation.
pub trait FromTransformedData<'a>: Sized {
pub trait FromTransformedData<'r>: Sized {
/// The associated error to be returned when the guard fails.
type Error: Send;
@ -367,7 +367,7 @@ pub trait FromTransformedData<'a>: Sized {
/// If transformation succeeds, an outcome of `Success` is returned.
/// If the data is not appropriate given the type of `Self`, `Forward` is
/// returned. On failure, `Failure` is returned.
fn transform<'r>(request: &'r Request<'_>, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error>;
fn transform(request: &'r Request<'_>, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error>;
/// Asynchronously validates, parses, and converts the incoming request body
/// data into an instance of `Self`.
@ -397,22 +397,22 @@ pub trait FromTransformedData<'a>: Sized {
/// # unimplemented!()
/// # }
/// ```
fn from_data(request: &'a Request<'_>, outcome: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error>;
fn from_data(request: &'r Request<'_>, outcome: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error>;
}
/// The identity implementation of `FromTransformedData`. Always returns `Success`.
impl<'a> FromTransformedData<'a> for Data {
impl<'r> FromTransformedData<'r> for Data {
type Error = std::convert::Infallible;
type Owned = Data;
type Borrowed = Data;
#[inline(always)]
fn transform<'r>(_: &'r Request<'_>, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
fn transform(_: &'r Request<'_>, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
Box::pin(ready(Transform::Owned(Success(data))))
}
#[inline(always)]
fn from_data(_: &'a Request<'_>, outcome: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error> {
fn from_data(_: &'r Request<'_>, outcome: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(ready(outcome.owned()))
}
}
@ -544,18 +544,18 @@ pub trait FromData: Sized {
async fn from_data(request: &Request<'_>, data: Data) -> Outcome<Self, Self::Error>;
}
impl<'a, T: FromData + 'a> FromTransformedData<'a> for T {
impl<'r, T: FromData + 'r> FromTransformedData<'r> for T {
type Error = T::Error;
type Owned = Data;
type Borrowed = Data;
#[inline(always)]
fn transform<'r>(_: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
fn transform(_: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
Box::pin(ready(Transform::Owned(Success(d))))
}
#[inline(always)]
fn from_data(req: &'a Request<'_>, o: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error> {
fn from_data(req: &'r Request<'_>, o: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
match o.owned() {
Success(data) => T::from_data(req, data),
_ => unreachable!(),
@ -563,18 +563,18 @@ impl<'a, T: FromData + 'a> FromTransformedData<'a> for T {
}
}
impl<'a, T: FromTransformedData<'a> + 'a> FromTransformedData<'a> for Result<T, T::Error> {
impl<'r, T: FromTransformedData<'r> + 'r> FromTransformedData<'r> for Result<T, T::Error> {
type Error = T::Error;
type Owned = T::Owned;
type Borrowed = T::Borrowed;
#[inline(always)]
fn transform<'r>(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
fn transform(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
T::transform(r, d)
}
#[inline(always)]
fn from_data(r: &'a Request<'_>, o: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error> {
fn from_data(r: &'r Request<'_>, o: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(T::from_data(r, o).map(|x| match x {
Success(val) => Success(Ok(val)),
Forward(data) => Forward(data),
@ -583,18 +583,18 @@ impl<'a, T: FromTransformedData<'a> + 'a> FromTransformedData<'a> for Result<T,
}
}
impl<'a, T: FromTransformedData<'a> + 'a> FromTransformedData<'a> for Option<T> {
impl<'r, T: FromTransformedData<'r> + 'r> FromTransformedData<'r> for Option<T> {
type Error = T::Error;
type Owned = T::Owned;
type Borrowed = T::Borrowed;
#[inline(always)]
fn transform<'r>(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
fn transform(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
T::transform(r, d)
}
#[inline(always)]
fn from_data(r: &'a Request<'_>, o: Transformed<'a, Self>) -> FromDataFuture<'a, Self, Self::Error> {
fn from_data(r: &'r Request<'_>, o: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(T::from_data(r, o).map(|x| match x {
Success(val) => Success(Some(val)),
Failure(_) | Forward(_) => Success(None),

View File

@ -248,7 +248,7 @@ impl Fairing for AdHoc {
}
}
async fn on_request(&self, req: &mut Request<'_>, data: &Data) {
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {
if let AdHocKind::Request(ref callback) = self.kind {
callback(req, data).await;
}

View File

@ -59,7 +59,7 @@ impl Fairings {
}
#[inline(always)]
pub async fn handle_request(&self, req: &mut Request<'_>, data: &Data) {
pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data) {
for &i in &self.request {
self.all_fairings[i].on_request(req, data).await;
}

View File

@ -217,7 +217,7 @@ pub use self::info_kind::{Info, Kind};
/// # unimplemented!()
/// }
///
/// async fn on_request(&self, req: &mut Request<'_>, data: &Data) {
/// async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {
/// /* ... */
/// # unimplemented!()
/// }
@ -266,7 +266,7 @@ pub use self::info_kind::{Info, Kind};
/// }
/// }
///
/// async fn on_request(&self, req: &mut Request<'_>, _: &Data) {
/// async fn on_request(&self, req: &mut Request<'_>, _: &mut Data) {
/// if req.method() == Method::Get {
/// self.get.fetch_add(1, Ordering::Relaxed);
/// } else if req.method() == Method::Post {
@ -329,7 +329,7 @@ pub use self::info_kind::{Info, Kind};
/// }
///
/// /// Stores the start time of the request in request-local state.
/// async fn on_request(&self, request: &mut Request<'_>, _: &Data) {
/// async fn on_request(&self, request: &mut Request<'_>, _: &mut Data) {
/// // Store a `TimerStart` instead of directly storing a `SystemTime`
/// // to ensure that this usage doesn't conflict with anything else
/// // that might store a `SystemTime` in request-local cache.
@ -440,7 +440,7 @@ pub trait Fairing: Send + Sync + 'static {
///
/// The default implementation of this method does nothing.
#[allow(unused_variables)]
async fn on_request(&self, req: &mut Request<'_>, data: &Data) {}
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {}
/// The response callback.
///
@ -474,7 +474,7 @@ impl<T: Fairing> Fairing for std::sync::Arc<T> {
}
#[inline]
async fn on_request(&self, req: &mut Request<'_>, data: &Data) {
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {
(self as &T).on_request(req, data).await;
}

View File

@ -183,12 +183,12 @@ impl<'f, T: FromForm<'f>> Form<T> {
///
/// All relevant warnings and errors are written to the console in Rocket
/// logging format.
impl<'f, T: FromForm<'f> + Send + 'f> FromTransformedData<'f> for Form<T> {
type Error = FormDataError<'f, T::Error>;
impl<'r, T: FromForm<'r> + Send + 'r> FromTransformedData<'r> for Form<T> {
type Error = FormDataError<'r, T::Error>;
type Owned = String;
type Borrowed = str;
fn transform<'r>(
fn transform(
request: &'r Request<'_>,
data: Data
) -> TransformFuture<'r, Self::Owned, Self::Error> {
@ -210,16 +210,16 @@ impl<'f, T: FromForm<'f> + Send + 'f> FromTransformedData<'f> for Form<T> {
}
fn from_data(
_: &'f Request<'_>,
o: Transformed<'f, Self>
) -> FromDataFuture<'f, Self, Self::Error> {
_: &'r Request<'_>,
o: Transformed<'r, Self>
) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(async move {
o.borrowed().and_then(|data| <Form<T>>::from_data(data, true).map(Form))
})
}
}
impl<'f, A, T: FromUriParam<Query, A> + FromForm<'f>> FromUriParam<Query, A> for Form<T> {
impl<'r, A, T: FromUriParam<Query, A> + FromForm<'r>> FromUriParam<Query, A> for Form<T> {
type Target = T::Target;
#[inline(always)]

View File

@ -93,23 +93,23 @@ impl<T> Deref for LenientForm<T> {
}
}
impl<'f, T: FromForm<'f> + Send + 'f> FromTransformedData<'f> for LenientForm<T> {
type Error = FormDataError<'f, T::Error>;
impl<'r, T: FromForm<'r> + Send + 'r> FromTransformedData<'r> for LenientForm<T> {
type Error = FormDataError<'r, T::Error>;
type Owned = String;
type Borrowed = str;
fn transform<'r>(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
fn transform(r: &'r Request<'_>, d: Data) -> TransformFuture<'r, Self::Owned, Self::Error> {
<Form<T>>::transform(r, d)
}
fn from_data(_: &'f Request<'_>, o: Transformed<'f, Self>) -> FromDataFuture<'f, Self, Self::Error> {
fn from_data(_: &'r Request<'_>, o: Transformed<'r, Self>) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(futures::future::ready(o.borrowed().and_then(|form| {
<Form<T>>::from_data(form, false).map(LenientForm)
})))
}
}
impl<'f, A, T: FromUriParam<Query, A> + FromForm<'f>> FromUriParam<Query, A> for LenientForm<T> {
impl<'r, A, T: FromUriParam<Query, A> + FromForm<'r>> FromUriParam<Query, A> for LenientForm<T> {
type Target = T::Target;
#[inline(always)]

View File

@ -26,7 +26,7 @@ impl Fairing for Counter {
}
}
async fn on_request(&self, request: &mut Request<'_>, _: &Data) {
async fn on_request(&self, request: &mut Request<'_>, _: &mut Data) {
if request.method() == Method::Get {
self.get.fetch_add(1, Ordering::Relaxed);
} else if request.method() == Method::Post {

View File

@ -169,7 +169,7 @@ impl Fairing for Counter {
}
// Increment the counter for `GET` and `POST` requests.
async fn on_request(&self, request: &mut Request<'_>, _: &Data) {
async fn on_request(&self, request: &mut Request<'_>, _: &mut Data) {
match request.method() {
Method::Get => self.get.fetch_add(1, Ordering::Relaxed),
Method::Post => self.post.fetch_add(1, Ordering::Relaxed),