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] #[rocket::async_trait]
impl Fairing for TemplateFairing { impl Fairing for TemplateFairing {
fn info(&self) -> Info { fn info(&self) -> Info {
// The on_request part of this fairing only applies in debug // on_request only applies in debug mode, so only enable it in debug.
// mode, so only register it in debug mode. #[cfg(debug_assertions)] let kind = Kind::Attach | Kind::Request;
#[cfg(debug_assertions)] #[cfg(not(debug_assertions))] let kind = Kind::Attach;
let info = Info {
name: "Templates",
kind: Kind::Attach | Kind::Request,
};
// FIXME: We declare two `info` variables here, instead of just one with Info { kind, name: "Templates" }
// `cfg`s on `kind`, due to issue #63 in `async_trait`.
#[cfg(not(debug_assertions))]
let info = Info {
name: "Templates",
kind: Kind::Attach,
};
info
} }
/// Initializes the template context. Templates will be searched for in the /// Initializes the template context. Templates will be searched for in the
@ -184,7 +172,7 @@ impl Fairing for TemplateFairing {
} }
#[cfg(debug_assertions)] #[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 let cm = req.guard::<rocket::State<'_, ContextManager>>().await
.expect("Template ContextManager registered in on_attach"); .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 /// method can be used to determine if this buffer contains _all_ of the
/// data in the body of the request. /// data in the body of the request.
/// ///
/// # Example /// # Examples
///
/// In a data guard:
/// ///
/// ```rust /// ```rust
/// use rocket::request::Request; /// use rocket::request::{self, Request, FromRequest};
/// use rocket::data::{self, Data, FromData}; /// use rocket::data::{self, Data, FromData};
/// # struct MyType; /// # struct MyType;
/// # type MyError = String; /// # type MyError = String;
@ -115,7 +117,7 @@ impl Data {
/// type Error = MyError; /// type Error = MyError;
/// ///
/// async fn from_data(req: &Request<'_>, mut data: Data) -> data::Outcome<Self, 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) /// 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] { pub async fn peek(&mut self, num: usize) -> &[u8] {
let num = std::cmp::min(PEEK_BYTES, num); let num = std::cmp::min(PEEK_BYTES, num);
let mut len = self.buffer.len(); let mut len = self.buffer.len();

View File

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

View File

@ -59,7 +59,7 @@ impl Fairings {
} }
#[inline(always)] #[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 { for &i in &self.request {
self.all_fairings[i].on_request(req, data).await; self.all_fairings[i].on_request(req, data).await;
} }

View File

@ -217,7 +217,7 @@ pub use self::info_kind::{Info, Kind};
/// # unimplemented!() /// # unimplemented!()
/// } /// }
/// ///
/// async fn on_request(&self, req: &mut Request<'_>, data: &Data) { /// async fn on_request(&self, req: &mut Request<'_>, data: &mut Data) {
/// /* ... */ /// /* ... */
/// # unimplemented!() /// # 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 { /// if req.method() == Method::Get {
/// self.get.fetch_add(1, Ordering::Relaxed); /// self.get.fetch_add(1, Ordering::Relaxed);
/// } else if req.method() == Method::Post { /// } 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. /// /// 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` /// // Store a `TimerStart` instead of directly storing a `SystemTime`
/// // to ensure that this usage doesn't conflict with anything else /// // to ensure that this usage doesn't conflict with anything else
/// // that might store a `SystemTime` in request-local cache. /// // 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. /// The default implementation of this method does nothing.
#[allow(unused_variables)] #[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. /// The response callback.
/// ///
@ -474,7 +474,7 @@ impl<T: Fairing> Fairing for std::sync::Arc<T> {
} }
#[inline] #[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; (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 /// All relevant warnings and errors are written to the console in Rocket
/// logging format. /// logging format.
impl<'f, T: FromForm<'f> + Send + 'f> FromTransformedData<'f> for Form<T> { impl<'r, T: FromForm<'r> + Send + 'r> FromTransformedData<'r> for Form<T> {
type Error = FormDataError<'f, T::Error>; type Error = FormDataError<'r, T::Error>;
type Owned = String; type Owned = String;
type Borrowed = str; type Borrowed = str;
fn transform<'r>( fn transform(
request: &'r Request<'_>, request: &'r Request<'_>,
data: Data data: Data
) -> TransformFuture<'r, Self::Owned, Self::Error> { ) -> 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( fn from_data(
_: &'f Request<'_>, _: &'r Request<'_>,
o: Transformed<'f, Self> o: Transformed<'r, Self>
) -> FromDataFuture<'f, Self, Self::Error> { ) -> FromDataFuture<'r, Self, Self::Error> {
Box::pin(async move { Box::pin(async move {
o.borrowed().and_then(|data| <Form<T>>::from_data(data, true).map(Form)) 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; type Target = T::Target;
#[inline(always)] #[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> { impl<'r, T: FromForm<'r> + Send + 'r> FromTransformedData<'r> for LenientForm<T> {
type Error = FormDataError<'f, T::Error>; type Error = FormDataError<'r, T::Error>;
type Owned = String; type Owned = String;
type Borrowed = str; 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) <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| { Box::pin(futures::future::ready(o.borrowed().and_then(|form| {
<Form<T>>::from_data(form, false).map(LenientForm) <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; type Target = T::Target;
#[inline(always)] #[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 { if request.method() == Method::Get {
self.get.fetch_add(1, Ordering::Relaxed); self.get.fetch_add(1, Ordering::Relaxed);
} else if request.method() == Method::Post { } else if request.method() == Method::Post {

View File

@ -169,7 +169,7 @@ impl Fairing for Counter {
} }
// Increment the counter for `GET` and `POST` requests. // 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() { match request.method() {
Method::Get => self.get.fetch_add(1, Ordering::Relaxed), Method::Get => self.get.fetch_add(1, Ordering::Relaxed),
Method::Post => self.post.fetch_add(1, Ordering::Relaxed), Method::Post => self.post.fetch_add(1, Ordering::Relaxed),