mirror of
https://github.com/rwf2/Rocket.git
synced 2025-01-17 23:19:06 +00:00
Update more API documentation to mention futures and async.
This commit is contained in:
parent
9a16aeb2e0
commit
e41abc09e5
@ -126,7 +126,7 @@ impl Data {
|
||||
self.is_complete
|
||||
}
|
||||
|
||||
/// A helper method to write the body of the request to any `Write` type.
|
||||
/// A helper method to write the body of the request to any `AsyncWrite` type.
|
||||
///
|
||||
/// This method is identical to `tokio::io::copy(&mut data.open(), &mut writer)`.
|
||||
///
|
||||
@ -152,7 +152,7 @@ impl Data {
|
||||
/// determined by `path`.
|
||||
///
|
||||
/// This method is identical to
|
||||
/// `io::copy(&mut self.open(), &mut File::create(path)?)`.
|
||||
/// `tokio::io::copy(&mut self.open(), &mut File::create(path).await?)`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -10,7 +10,7 @@ use crate::ext::AsyncReadBody;
|
||||
/// This stream can only be obtained by calling
|
||||
/// [`Data::open()`](crate::data::Data::open()). The stream contains all of the data
|
||||
/// in the body of the request. It exposes no methods directly. Instead, it must
|
||||
/// be used as an opaque [`Read`] structure.
|
||||
/// be used as an opaque [`AsyncRead`] structure.
|
||||
pub struct DataStream(pub(crate) Vec<u8>, pub(crate) AsyncReadBody);
|
||||
|
||||
// TODO.async: Consider implementing `AsyncBufRead`
|
||||
|
@ -112,7 +112,10 @@ pub type Transformed<'a, T> =
|
||||
Outcome<&'a <T as FromData<'a>>::Borrowed, <T as FromData<'a>>::Error>
|
||||
>;
|
||||
|
||||
/// Type alias to the `Future` returned by [`FromData::transform`].
|
||||
pub type TransformFuture<'fut, T, E> = BoxFuture<'fut, Transform<Outcome<T, E>>>;
|
||||
|
||||
/// Type alias to the `Future` returned by [`FromData::from_data`].
|
||||
pub type FromDataFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
|
||||
|
||||
/// Trait implemented by data guards to derive a value from request body data.
|
||||
@ -161,14 +164,15 @@ pub type FromDataFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
|
||||
/// implement `FromDataSimple` automatically implement `FromData`.
|
||||
///
|
||||
/// When exercising a data guard, Rocket first calls the guard's
|
||||
/// [`FromData::transform()`] method and then subsequently calls the guard's
|
||||
/// [`FromData::from_data()`] method. Rocket stores data returned by
|
||||
/// [`FromData::transform()`] on the stack. If `transform` returns a
|
||||
/// [`Transform::Owned`], Rocket moves the data back to the data guard in the
|
||||
/// subsequent `from_data` call as a `Transform::Owned`. If instead `transform`
|
||||
/// returns a [`Transform::Borrowed`] variant, Rocket calls `borrow()` on the
|
||||
/// owned value, producing a borrow of the associated [`FromData::Borrowed`]
|
||||
/// type and passing it as a `Transform::Borrowed`.
|
||||
/// [`FromData::transform()`] method and awaits on the returned future, then
|
||||
/// calls the guard's [`FromData::from_data()`] method and awaits on that
|
||||
/// returned future. Rocket stores data returned by [`FromData::transform()`] on
|
||||
/// the stack. If `transform` returns a [`Transform::Owned`], Rocket moves the
|
||||
/// data back to the data guard in the subsequent `from_data` call as a
|
||||
/// `Transform::Owned`. If instead `transform` returns a [`Transform::Borrowed`]
|
||||
/// variant, Rocket calls `borrow()` on the owned value, producing a borrow of
|
||||
/// the associated [`FromData::Borrowed`] type and passing it as a
|
||||
/// `Transform::Borrowed`.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
@ -349,11 +353,11 @@ pub trait FromData<'a>: Sized {
|
||||
/// associated type should be set to `Self::Owned`.
|
||||
type Borrowed: ?Sized;
|
||||
|
||||
/// Transforms `data` into a value of type `Self::Owned`.
|
||||
/// Asynchronously transforms `data` into a value of type `Self::Owned`.
|
||||
///
|
||||
/// If this method returns a `Transform::Owned(Self::Owned)`, then
|
||||
/// If the returned future resolves to `Transform::Owned(Self::Owned)`, then
|
||||
/// `from_data` should subsequently be called with a `data` value of
|
||||
/// `Transform::Owned(Self::Owned)`. If this method returns a
|
||||
/// `Transform::Owned(Self::Owned)`. If the future resolves to
|
||||
/// `Transform::Borrowed(Self::Owned)`, `from_data` should subsequently be
|
||||
/// called with a `data` value of `Transform::Borrowed(&Self::Borrowed)`. In
|
||||
/// other words, the variant of `Transform` returned from this method is
|
||||
@ -369,8 +373,8 @@ pub trait FromData<'a>: Sized {
|
||||
/// returned. On failure, `Failure` is returned.
|
||||
fn transform<'r>(request: &'r Request<'_>, data: Data) -> TransformFuture<'r, Self::Owned, Self::Error>;
|
||||
|
||||
/// Validates, parses, and converts the incoming request body data into an
|
||||
/// instance of `Self`.
|
||||
/// Asynchronously validates, parses, and converts the incoming request body
|
||||
/// data into an instance of `Self`.
|
||||
///
|
||||
/// If validation and parsing succeeds, an outcome of `Success` is returned.
|
||||
/// If the data is not appropriate given the type of `Self`, `Forward` is
|
||||
@ -512,12 +516,11 @@ impl<'a> FromData<'a> for Data {
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
pub trait FromDataSimple: Sized {
|
||||
// TODO.async: Can/should we relax this 'static? And how?
|
||||
/// The associated error to be returned when the guard fails.
|
||||
type Error: Send + 'static;
|
||||
|
||||
/// Validates, parses, and converts an instance of `Self` from the incoming
|
||||
/// request body data.
|
||||
/// Asynchronously validates, parses, and converts an instance of `Self`
|
||||
/// from the incoming request body data.
|
||||
///
|
||||
/// If validation and parsing succeeds, an outcome of `Success` is returned.
|
||||
/// If the data is not appropriate given the type of `Self`, `Forward` is
|
||||
|
@ -94,7 +94,8 @@ impl AdHoc {
|
||||
}
|
||||
|
||||
/// Constructs an `AdHoc` request fairing named `name`. The function `f`
|
||||
/// will be called by Rocket when a new request is received.
|
||||
/// will be called and the returned `Future` will be `await`ed by Rocket
|
||||
/// when a new request is received.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -116,7 +117,8 @@ impl AdHoc {
|
||||
}
|
||||
|
||||
/// Constructs an `AdHoc` response fairing named `name`. The function `f`
|
||||
/// will be called by Rocket when a response is ready to be sent.
|
||||
/// will be called and the returned `Future` will be `await`ed by Rocket
|
||||
/// when a response is ready to be sent.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -140,13 +140,13 @@ pub trait Handler: Cloneable + Send + Sync + 'static {
|
||||
/// Called by Rocket when a `Request` with its associated `Data` should be
|
||||
/// handled by this handler.
|
||||
///
|
||||
/// The variant of `Outcome` returned determines 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 is a
|
||||
/// `Failure(Status)`, the error catcher for `Status` is invoked to generate
|
||||
/// a response. Otherwise, if the return value is `Forward(Data)`, the next
|
||||
/// matching route is attempted. If there are no other matching routes, the
|
||||
/// `404` error catcher is invoked.
|
||||
/// The variant of `Outcome` returned by the returned `Future` determines
|
||||
/// 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
|
||||
/// is a `Failure(Status)`, the error catcher for `Status` is invoked to
|
||||
/// generate a response. Otherwise, if the return value is `Forward(Data)`,
|
||||
/// the next matching route is attempted. If there are no other matching
|
||||
/// routes, the `404` error catcher is invoked.
|
||||
fn handle<'r>(&self, request: &'r Request<'_>, data: Data) -> HandlerFuture<'r>;
|
||||
}
|
||||
|
||||
@ -186,6 +186,7 @@ impl<F: Clone + Sync + Send + 'static> Handler for F
|
||||
/// The type of an error handler.
|
||||
pub type ErrorHandler = for<'r> fn(&'r Request<'_>) -> ErrorHandlerFuture<'r>;
|
||||
|
||||
/// Type type of `Future` returned by an error handler.
|
||||
pub type ErrorHandlerFuture<'r> = BoxFuture<'r, response::Result<'r>>;
|
||||
|
||||
impl<'r> Outcome<'r> {
|
||||
|
@ -37,6 +37,68 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||
/// Type alias for the future returned by [`FromRequestAsync::from_request`].
|
||||
pub type FromRequestFuture<'fut, T, E> = BoxFuture<'fut, Outcome<T, E>>;
|
||||
|
||||
/// Trait implemented by asynchronous request guards to derive a value from
|
||||
/// incoming requests.
|
||||
///
|
||||
/// For more information on request guards in general, see the [`FromRequest`]
|
||||
/// trait.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// Imagine you're running an authenticated service backed by a database. You
|
||||
/// want to ensure that certain handlers will only run if a valid API key is
|
||||
/// present in the request, and you need to make a database request in order to
|
||||
/// determine if the key is valid or not.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![feature(proc_macro_hygiene)]
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// #
|
||||
/// # struct Database;
|
||||
/// # impl Database {
|
||||
/// # async fn check_key(&self, key: &str) -> bool {
|
||||
/// # true
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use rocket::Outcome;
|
||||
/// use rocket::http::Status;
|
||||
/// use rocket::request::{self, Request, State, FromRequestAsync};
|
||||
///
|
||||
/// struct ApiKey(String);
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// enum ApiKeyError {
|
||||
/// BadCount,
|
||||
/// Missing,
|
||||
/// Invalid,
|
||||
/// }
|
||||
///
|
||||
/// impl<'a, 'r> FromRequestAsync<'a, 'r> for ApiKey {
|
||||
/// type Error = ApiKeyError;
|
||||
///
|
||||
/// fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> {
|
||||
/// Box::pin(async move {
|
||||
/// let keys: Vec<_> = request.headers().get("x-api-key").collect();
|
||||
/// let database: State<'_, Database> = request.guard().expect("get database connection");
|
||||
/// match keys.len() {
|
||||
/// 0 => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
|
||||
/// 1 if database.check_key(keys[0]).await => Outcome::Success(ApiKey(keys[0].to_string())),
|
||||
/// 1 => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
|
||||
/// _ => Outcome::Failure((Status::BadRequest, ApiKeyError::BadCount)),
|
||||
/// }
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[get("/sensitive")]
|
||||
/// fn sensitive(key: ApiKey) -> &'static str {
|
||||
/// # let _key = key;
|
||||
/// "Sensitive data."
|
||||
/// }
|
||||
///
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
pub trait FromRequestAsync<'a, 'r>: Sized {
|
||||
/// The associated error to be returned if derivation fails.
|
||||
type Error: Debug;
|
||||
@ -65,6 +127,10 @@ pub trait FromRequestAsync<'a, 'r>: Sized {
|
||||
/// the handler. Rocket only dispatches requests to a handler when all of its
|
||||
/// guards pass.
|
||||
///
|
||||
/// Request guards can be made *asynchronous* by implementing
|
||||
/// [`FromRequestAsync`] instead of `FromRequest`. This is useful when the
|
||||
/// validation requires working with a database or performing other I/O.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// The following dummy handler makes use of three request guards, `A`, `B`, and
|
||||
|
@ -48,5 +48,6 @@ pub use self::debug::Debug;
|
||||
|
||||
/// Type alias for the `Result` of a `Responder::respond` call.
|
||||
pub type Result<'r> = std::result::Result<self::Response<'r>, crate::http::Status>;
|
||||
/// Type alias for the `Result` of a `Responder::respond` call.
|
||||
|
||||
/// Type alias for the `Future` returned by a `Responder::respond` call.
|
||||
pub type ResultFuture<'r> = futures_util::future::BoxFuture<'r, Result<'r>>;
|
||||
|
@ -26,7 +26,8 @@ use crate::request::Request;
|
||||
///
|
||||
/// # Return Value
|
||||
///
|
||||
/// A `Responder` returns an `Ok(Response)` or an `Err(Status)`:
|
||||
/// A `Responder` returns a `Future` whose output type is an `Ok(Response)` or
|
||||
/// an `Err(Status)`:
|
||||
///
|
||||
/// * An `Ok` variant means that the `Responder` was successful in generating
|
||||
/// a `Response`. The `Response` will be written out to the client.
|
||||
@ -84,14 +85,7 @@ use crate::request::Request;
|
||||
/// the client. Otherwise, an `Err` with status **404 Not Found** is
|
||||
/// returned and a warning is printed to the console.
|
||||
///
|
||||
/// * **Result<T, E>** _where_ **E: Debug**
|
||||
///
|
||||
/// If the `Result` is `Ok`, the wrapped responder is used to respond to the
|
||||
/// client. Otherwise, an `Err` with status **500 Internal Server Error** is
|
||||
/// returned and the error is printed to the console using the `Debug`
|
||||
/// implementation.
|
||||
///
|
||||
/// * **Result<T, E>** _where_ **E: Debug + Responder**
|
||||
/// * **Result<T, E>**
|
||||
///
|
||||
/// If the `Result` is `Ok`, the wrapped `Ok` responder is used to respond
|
||||
/// to the client. If the `Result` is `Err`, the wrapped `Err` responder is
|
||||
@ -102,13 +96,6 @@ use crate::request::Request;
|
||||
/// This section describes a few best practices to take into account when
|
||||
/// implementing `Responder`.
|
||||
///
|
||||
/// ## Debug
|
||||
///
|
||||
/// A type implementing `Responder` should implement the `Debug` trait when
|
||||
/// possible. This is because the `Responder` implementation for `Result`
|
||||
/// requires its `Err` type to implement `Debug`. Therefore, a type implementing
|
||||
/// `Debug` can more easily be composed.
|
||||
///
|
||||
/// ## Joining and Merging
|
||||
///
|
||||
/// When chaining/wrapping other `Responder`s, use the
|
||||
@ -277,7 +264,7 @@ impl Responder<'_> for () {
|
||||
|
||||
/// If `self` is `Some`, responds with the wrapped `Responder`. Otherwise prints
|
||||
/// a warning message and returns an `Err` of `Status::NotFound`.
|
||||
impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Option<R> {
|
||||
impl<'r, R: Responder<'r>> Responder<'r> for Option<R> {
|
||||
fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> {
|
||||
match self {
|
||||
Some(r) => r.respond_to(req),
|
||||
@ -291,7 +278,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Option<R> {
|
||||
|
||||
/// Responds with the wrapped `Responder` in `self`, whether it is `Ok` or
|
||||
/// `Err`.
|
||||
impl<'r, R: Responder<'r> + Send + 'r, E: Responder<'r> + Send + 'r> Responder<'r> for Result<R, E> {
|
||||
impl<'r, R: Responder<'r>, E: Responder<'r>> Responder<'r> for Result<R, E> {
|
||||
fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> {
|
||||
match self {
|
||||
Ok(responder) => responder.respond_to(req),
|
||||
|
@ -772,9 +772,9 @@ impl Rocket {
|
||||
.map_err(crate::error::Error::Run)
|
||||
}
|
||||
|
||||
/// Returns a `Future` that completes when the server is shut down or
|
||||
/// errors. If the `ctrl_c_shutdown` feature is enabled, `Ctrl-C` will be
|
||||
/// handled as a shutdown signal.
|
||||
/// Returns a `Future` that drives the server and completes when the server
|
||||
/// is shut down or errors. If the `ctrl_c_shutdown` feature is enabled,
|
||||
/// the server will shut down gracefully once `Ctrl-C` is pressed.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -870,6 +870,10 @@ impl Rocket {
|
||||
/// unless a shutdown is requested via a [`ShutdownHandle`] or there is an
|
||||
/// error.
|
||||
///
|
||||
/// This is a convenience function that creates a suitable default runtime
|
||||
/// and launches the server on that runtime. If you already have a runtime,
|
||||
/// use the [`Rocket::serve`] method instead.
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// If there is a problem starting the application, a [`LaunchError`] is
|
||||
|
@ -1,6 +1,12 @@
|
||||
use crate::request::{FromRequest, Outcome, Request};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
/// A `ShutdownHandle` can be used to instruct a Rocket server to gracefully
|
||||
/// shut down. Once a server shutdown has been requested manually by calling
|
||||
/// [`ShutdownHandle::shutdown()`] or automatically by `Ctrl-C` being pressed
|
||||
/// (if enabled), Rocket will finish handling any pending requests and return to
|
||||
/// the caller of [`Rocket::serve`] or [`Rocket::launch`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
@ -28,7 +34,9 @@ use tokio::sync::mpsc;
|
||||
pub struct ShutdownHandle(pub(crate) mpsc::Sender<()>);
|
||||
|
||||
impl ShutdownHandle {
|
||||
/// Notify Rocket to shut down gracefully.
|
||||
/// Notify Rocket to shut down gracefully. This function returns
|
||||
/// immediately; pending requests will continue to run until completion
|
||||
/// before the actual shutdown occurs.
|
||||
#[inline]
|
||||
pub fn shutdown(mut self) {
|
||||
// Intentionally ignore any error, as the only scenarios this can happen
|
||||
|
Loading…
Reference in New Issue
Block a user