//! Request extractors use actix_http::error::Error; use futures::future::ok; use futures::{future, Async, Future, IntoFuture, Poll}; use crate::dev::Payload; use crate::request::HttpRequest; /// Trait implemented by types that can be extracted from request. /// /// Types that implement this trait can be used with `Route` handlers. pub trait FromRequest
: Sized {
/// The associated error which can be returned.
type Error: Into ) -> Self::Future;
/// Convert request to a Self
///
/// This method uses `Payload::None` as payload stream.
fn extract(req: &HttpRequest) -> Self::Future {
Self::from_request(req, &mut Payload::None)
}
}
/// Optionally extract a field from the request
///
/// If the FromRequest for T fails, return None rather than returning an error response
///
/// ## Example
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// use actix_web::{web, dev, App, Error, HttpRequest, FromRequest};
/// use actix_web::error::ErrorBadRequest;
/// use rand;
///
/// #[derive(Debug, Deserialize)]
/// struct Thing {
/// name: String
/// }
///
/// impl FromRequest for Thing {
/// type Error = Error;
/// type Future = Result ) -> Self::Future {
/// if rand::random() {
/// Ok(Thing { name: "thingy".into() })
/// } else {
/// Err(ErrorBadRequest("no luck"))
/// }
///
/// }
/// }
///
/// /// extract `Thing` from request
/// fn index(supplied_thing: Option for Option ,
T::Future: 'static,
{
type Error = Error;
type Future = Box ) -> Self::Future {
Box::new(
T::from_request(req, payload)
.into_future()
.then(|r| match r {
Ok(v) => future::ok(Some(v)),
Err(e) => {
log::debug!("Error for Option FromRequest for Thing {
/// type Error = Error;
/// type Future = Result ) -> Self::Future {
/// if rand::random() {
/// Ok(Thing { name: "thingy".into() })
/// } else {
/// Err(ErrorBadRequest("no luck"))
/// }
/// }
/// }
///
/// /// extract `Thing` from request
/// fn index(supplied_thing: Result for Result ,
T::Future: 'static,
T::Error: 'static,
{
type Error = Error;
type Future = Box ) -> Self::Future {
Box::new(
T::from_request(req, payload)
.into_future()
.then(|res| match res {
Ok(v) => ok(Ok(v)),
Err(e) => ok(Err(e)),
}),
)
}
}
#[doc(hidden)]
impl FromRequest for () {
type Error = Error;
type Future = Result<(), Error>;
fn from_request(_: &HttpRequest, _: &mut Payload ) -> Self::Future {
Ok(())
}
}
macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
/// FromRequest implementation for tuple
#[doc(hidden)]
impl + 'static),+> FromRequest for ($($T,)+)
{
type Error = Error;
type Future = $fut_type ;
fn from_request(req: &HttpRequest, payload: &mut Payload ) -> Self::Future {
$fut_type {
items: <($(Option<$T>,)+)>::default(),
futs: ($($T::from_request(req, payload).into_future(),)+),
}
}
}
#[doc(hidden)]
pub struct $fut_type ),+> {
items: ($(Option<$T>,)+),
futs: ($(<$T::Future as futures::IntoFuture>::Future,)+),
}
impl ),+> Future for $fut_type
{
type Item = ($($T,)+);
type Error = Error;
fn poll(&mut self) -> Poll