mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
rename extractor module to extract, re-enable doc tests
This commit is contained in:
parent
237677be15
commit
e50d4c5e0e
@ -52,7 +52,6 @@ actix-router = { git = "https://github.com/actix/actix-net.git" }
|
|||||||
|
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
derive_more = "0.14"
|
derive_more = "0.14"
|
||||||
either = "1.5.1"
|
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -20,65 +20,103 @@ use actix_http::error::{
|
|||||||
UrlencodedError,
|
UrlencodedError,
|
||||||
};
|
};
|
||||||
use actix_http::http::StatusCode;
|
use actix_http::http::StatusCode;
|
||||||
use actix_http::{HttpMessage, Response};
|
use actix_http::{Extensions, HttpMessage, Response};
|
||||||
use actix_router::PathDeserializer;
|
use actix_router::PathDeserializer;
|
||||||
|
|
||||||
use crate::handler::{ConfigStorage, ExtractorConfig, FromRequest};
|
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::service::ServiceFromRequest;
|
use crate::service::ServiceFromRequest;
|
||||||
|
|
||||||
|
/// Trait implemented by types that can be extracted from request.
|
||||||
|
///
|
||||||
|
/// Types that implement this trait can be used with `Route` handlers.
|
||||||
|
pub trait FromRequest<P>: Sized {
|
||||||
|
/// The associated error which can be returned.
|
||||||
|
type Error: Into<Error>;
|
||||||
|
|
||||||
|
/// Future that resolves to a Self
|
||||||
|
type Future: IntoFuture<Item = Self, Error = Self::Error>;
|
||||||
|
|
||||||
|
/// Configuration for the extractor
|
||||||
|
type Config: ExtractorConfig;
|
||||||
|
|
||||||
|
/// Convert request to a Self
|
||||||
|
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Storage for extractor configs
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ConfigStorage {
|
||||||
|
pub(crate) storage: Option<Rc<Extensions>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigStorage {
|
||||||
|
pub fn store<C: ExtractorConfig>(&mut self, config: C) {
|
||||||
|
if self.storage.is_none() {
|
||||||
|
self.storage = Some(Rc::new(Extensions::new()));
|
||||||
|
}
|
||||||
|
if let Some(ref mut ext) = self.storage {
|
||||||
|
Rc::get_mut(ext).unwrap().insert(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ExtractorConfig: Default + Clone + 'static {
|
||||||
|
/// Set default configuration to config storage
|
||||||
|
fn store_default(ext: &mut ConfigStorage) {
|
||||||
|
ext.store(Self::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtractorConfig for () {
|
||||||
|
fn store_default(_: &mut ConfigStorage) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
/// Extract typed information from the request's path.
|
/// Extract typed information from the request's path.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate bytes;
|
/// use actix_web::{web, http, App, extract::Path};
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// # extern crate futures;
|
|
||||||
/// use actix_web::{http, App, Path, Result};
|
|
||||||
///
|
///
|
||||||
/// /// extract path info from "/{username}/{count}/index.html" url
|
/// /// extract path info from "/{username}/{count}/index.html" url
|
||||||
/// /// {username} - deserializes to a String
|
/// /// {username} - deserializes to a String
|
||||||
/// /// {count} - - deserializes to a u32
|
/// /// {count} - - deserializes to a u32
|
||||||
/// fn index(info: Path<(String, u32)>) -> Result<String> {
|
/// fn index(info: Path<(String, u32)>) -> String {
|
||||||
/// Ok(format!("Welcome {}! {}", info.0, info.1))
|
/// format!("Welcome {}! {}", info.0, info.1)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/{username}/{count}/index.html", // <- define path parameters
|
/// "/{username}/{count}/index.html", // <- define path parameters
|
||||||
/// |r| r.method(http::Method::GET).with(index),
|
/// |r| r.route(web::get().to(index)) // <- register handler with `Path` extractor
|
||||||
/// ); // <- use `with` extractor
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// It is possible to extract path information to a specific type that
|
/// It is possible to extract path information to a specific type that
|
||||||
/// implements `Deserialize` trait from *serde*.
|
/// implements `Deserialize` trait from *serde*.
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate bytes;
|
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// # extern crate futures;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{http, App, Path, Result};
|
/// use actix_web::{web, App, extract::Path, Error};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
/// username: String,
|
/// username: String,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// extract path info using serde
|
/// /// extract `Info` from a path using serde
|
||||||
/// fn index(info: Path<Info>) -> Result<String> {
|
/// fn index(info: Path<Info>) -> Result<String, Error> {
|
||||||
/// Ok(format!("Welcome {}!", info.username))
|
/// Ok(format!("Welcome {}!", info.username))
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/{username}/index.html", // <- define path parameters
|
/// "/{username}/index.html", // <- define path parameters
|
||||||
/// |r| r.method(http::Method::GET).with(index),
|
/// |r| r.route(web::get().to(index)) // <- use handler with Path` extractor
|
||||||
/// ); // <- use `with` extractor
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Path<T> {
|
pub struct Path<T> {
|
||||||
@ -112,7 +150,7 @@ impl<T> Path<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extract path information from a request
|
/// Extract path information from a request
|
||||||
pub fn extract<P>(req: &ServiceFromRequest<P>) -> Result<Path<T>, de::value::Error>
|
pub fn extract(req: &HttpRequest) -> Result<Path<T>, de::value::Error>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
{
|
{
|
||||||
@ -158,13 +196,9 @@ impl<T: fmt::Display> fmt::Display for Path<T> {
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate bytes;
|
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// # extern crate futures;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{App, Query, http};
|
/// use actix_web::{web, extract, App};
|
||||||
///
|
|
||||||
///
|
///
|
||||||
///#[derive(Debug, Deserialize)]
|
///#[derive(Debug, Deserialize)]
|
||||||
///pub enum ResponseType {
|
///pub enum ResponseType {
|
||||||
@ -178,17 +212,17 @@ impl<T: fmt::Display> fmt::Display for Path<T> {
|
|||||||
/// response_type: ResponseType,
|
/// response_type: ResponseType,
|
||||||
///}
|
///}
|
||||||
///
|
///
|
||||||
/// // use `with` extractor for query info
|
/// // Use `Query` extractor for query information.
|
||||||
/// // this handler get called only if request's query contains `username` field
|
/// // This handler get called only if request's query contains `username` field
|
||||||
/// // The correct request for this handler would be `/index.html?id=64&response_type=Code"`
|
/// // The correct request for this handler would be `/index.html?id=64&response_type=Code"`
|
||||||
/// fn index(info: Query<AuthRequest>) -> String {
|
/// fn index(info: extract::Query<AuthRequest>) -> String {
|
||||||
/// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type)
|
/// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/index.html",
|
/// "/index.html",
|
||||||
/// |r| r.method(http::Method::GET).with(index)); // <- use `with` extractor
|
/// |r| r.route(web::get().to(index))); // <- use `Query` extractor
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Query<T>(T);
|
pub struct Query<T>(T);
|
||||||
@ -253,21 +287,21 @@ impl<T: fmt::Display> fmt::Display for Query<T> {
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # extern crate actix_web;
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{App, Form, Result};
|
/// use actix_web::{web, App, extract::Form};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct FormData {
|
/// struct FormData {
|
||||||
/// username: String,
|
/// username: String,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// extract form data using serde
|
/// /// Extract form data using serde.
|
||||||
/// /// this handler get called only if content type is *x-www-form-urlencoded*
|
/// /// This handler get called only if content type is *x-www-form-urlencoded*
|
||||||
/// /// and content of the request could be deserialized to a `FormData` struct
|
/// /// and content of the request could be deserialized to a `FormData` struct
|
||||||
/// fn index(form: Form<FormData>) -> Result<String> {
|
/// fn index(form: Form<FormData>) -> String {
|
||||||
/// Ok(format!("Welcome {}!", form.username))
|
/// format!("Welcome {}!", form.username)
|
||||||
/// }
|
/// }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
@ -333,19 +367,18 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
|
|||||||
|
|
||||||
/// Form extractor configuration
|
/// Form extractor configuration
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{http, App, Form, Result};
|
/// use actix_web::{web, extract, App, Result};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct FormData {
|
/// struct FormData {
|
||||||
/// username: String,
|
/// username: String,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// extract form data using serde.
|
/// /// Extract form data using serde.
|
||||||
/// /// custom configuration is used for this handler, max payload size is 4k
|
/// /// Custom configuration is used for this handler, max payload size is 4k
|
||||||
/// fn index(form: Form<FormData>) -> Result<String> {
|
/// fn index(form: extract::Form<FormData>) -> Result<String> {
|
||||||
/// Ok(format!("Welcome {}!", form.username))
|
/// Ok(format!("Welcome {}!", form.username))
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -353,11 +386,11 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
|
|||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/index.html",
|
/// "/index.html",
|
||||||
/// |r| {
|
/// |r| {
|
||||||
/// r.method(http::Method::GET)
|
/// r.route(web::get()
|
||||||
/// // register form handler and change form extractor configuration
|
/// // change `Form` extractor configuration
|
||||||
/// .with_config(index, |cfg| {cfg.0.limit(4096);})
|
/// .config(extract::FormConfig::default().limit(4097))
|
||||||
/// },
|
/// .to(index))
|
||||||
/// );
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -408,10 +441,9 @@ impl Default for FormConfig {
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{App, Json, Result, http};
|
/// use actix_web::{web, extract, App};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
@ -419,14 +451,14 @@ impl Default for FormConfig {
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// deserialize `Info` from request's body
|
/// /// deserialize `Info` from request's body
|
||||||
/// fn index(info: Json<Info>) -> Result<String> {
|
/// fn index(info: extract::Json<Info>) -> String {
|
||||||
/// Ok(format!("Welcome {}!", info.username))
|
/// format!("Welcome {}!", info.username)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/index.html",
|
/// "/index.html",
|
||||||
/// |r| r.method(http::Method::POST).with(index)); // <- use `with` extractor
|
/// |r| r.route(web::post().to(index)));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -435,8 +467,7 @@ impl Default for FormConfig {
|
|||||||
/// to serialize into *JSON*. The type `T` must implement the `Serialize`
|
/// to serialize into *JSON*. The type `T` must implement the `Serialize`
|
||||||
/// trait from *serde*.
|
/// trait from *serde*.
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// # #[macro_use] extern crate serde_derive;
|
/// # #[macro_use] extern crate serde_derive;
|
||||||
/// # use actix_web::*;
|
/// # use actix_web::*;
|
||||||
/// #
|
/// #
|
||||||
@ -447,7 +478,7 @@ impl Default for FormConfig {
|
|||||||
///
|
///
|
||||||
/// fn index(req: HttpRequest) -> Result<Json<MyObj>> {
|
/// fn index(req: HttpRequest) -> Result<Json<MyObj>> {
|
||||||
/// Ok(Json(MyObj {
|
/// Ok(Json(MyObj {
|
||||||
/// name: req.match_info().query("name")?,
|
/// name: req.match_info().get("name").unwrap().to_string(),
|
||||||
/// }))
|
/// }))
|
||||||
/// }
|
/// }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
@ -536,10 +567,9 @@ where
|
|||||||
|
|
||||||
/// Json extractor configuration
|
/// Json extractor configuration
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{error, http, App, HttpResponse, Json, Result};
|
/// use actix_web::{error, extract, web, App, HttpResponse, Json};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
@ -547,20 +577,20 @@ where
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// deserialize `Info` from request's body, max payload size is 4kb
|
/// /// deserialize `Info` from request's body, max payload size is 4kb
|
||||||
/// fn index(info: Json<Info>) -> Result<String> {
|
/// fn index(info: Json<Info>) -> String {
|
||||||
/// Ok(format!("Welcome {}!", info.username))
|
/// format!("Welcome {}!", info.username)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource("/index.html", |r| {
|
/// let app = App::new().resource("/index.html", |r| {
|
||||||
/// r.method(http::Method::POST)
|
/// r.route(web::post().config(
|
||||||
/// .with_config(index, |cfg| {
|
/// // change json extractor configuration
|
||||||
/// cfg.0.limit(4096) // <- change json extractor configuration
|
/// extract::JsonConfig::default().limit(4096)
|
||||||
/// .error_handler(|err, req| { // <- create custom error response
|
/// .error_handler(|err, req| { // <- create custom error response
|
||||||
/// error::InternalError::from_response(
|
/// error::InternalError::from_response(
|
||||||
/// err, HttpResponse::Conflict().finish()).into()
|
/// err, HttpResponse::Conflict().finish()).into()
|
||||||
/// });
|
/// }))
|
||||||
/// })
|
/// .to(index))
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -598,7 +628,7 @@ impl Default for JsonConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request payload extractor.
|
/// Request binary data from a request's payload.
|
||||||
///
|
///
|
||||||
/// Loads request's payload and construct Bytes instance.
|
/// Loads request's payload and construct Bytes instance.
|
||||||
///
|
///
|
||||||
@ -607,19 +637,18 @@ impl Default for JsonConfig {
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// extern crate bytes;
|
/// use bytes::Bytes;
|
||||||
/// # extern crate actix_web;
|
/// use actix_web::{web, App};
|
||||||
/// use actix_web::{http, App, Result};
|
|
||||||
///
|
///
|
||||||
/// /// extract text data from request
|
/// /// extract binary data from request
|
||||||
/// fn index(body: bytes::Bytes) -> Result<String> {
|
/// fn index(body: Bytes) -> String {
|
||||||
/// Ok(format!("Body {:?}!", body))
|
/// format!("Body {:?}!", body)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new()
|
/// let app = App::new()
|
||||||
/// .resource("/index.html", |r| r.method(http::Method::GET).with(index));
|
/// .resource("/index.html", |r| r.route(web::get().to(index)));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
impl<P> FromRequest<P> for Bytes
|
impl<P> FromRequest<P> for Bytes
|
||||||
@ -644,7 +673,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract text information from the request's body.
|
/// Extract text information from a request's body.
|
||||||
///
|
///
|
||||||
/// Text extractor automatically decode body according to the request's charset.
|
/// Text extractor automatically decode body according to the request's charset.
|
||||||
///
|
///
|
||||||
@ -653,21 +682,20 @@ where
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// use actix_web::{web, extract, App};
|
||||||
/// use actix_web::{http, App, Result};
|
|
||||||
///
|
///
|
||||||
/// /// extract text data from request
|
/// /// extract text data from request
|
||||||
/// fn index(body: String) -> Result<String> {
|
/// fn index(text: String) -> String {
|
||||||
/// Ok(format!("Body {}!", body))
|
/// format!("Body {}!", text)
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource("/index.html", |r| {
|
/// let app = App::new().resource("/index.html", |r| {
|
||||||
/// r.method(http::Method::GET)
|
/// r.route(
|
||||||
/// .with_config(index, |cfg| { // <- register handler with extractor params
|
/// web::get()
|
||||||
/// cfg.0.limit(4096); // <- limit size of the payload
|
/// .config(extract::PayloadConfig::new(4096)) // <- limit size of the payload
|
||||||
/// })
|
/// .to(index)) // <- register handler with extractor params
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -722,22 +750,23 @@ where
|
|||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # #[macro_use] extern crate serde_derive;
|
||||||
/// extern crate rand;
|
/// use actix_web::{web, App, Error, FromRequest, ServiceFromRequest};
|
||||||
/// #[macro_use] extern crate serde_derive;
|
|
||||||
/// use actix_web::{http, App, Result, HttpRequest, Error, FromRequest};
|
|
||||||
/// use actix_web::error::ErrorBadRequest;
|
/// use actix_web::error::ErrorBadRequest;
|
||||||
|
/// use rand;
|
||||||
///
|
///
|
||||||
/// #[derive(Debug, Deserialize)]
|
/// #[derive(Debug, Deserialize)]
|
||||||
/// struct Thing { name: String }
|
/// struct Thing {
|
||||||
|
/// name: String
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// impl<S> FromRequest<S> for Thing {
|
/// impl<P> FromRequest<P> for Thing {
|
||||||
|
/// type Error = Error;
|
||||||
|
/// type Future = Result<Self, Self::Error>;
|
||||||
/// type Config = ();
|
/// type Config = ();
|
||||||
/// type Result = Result<Thing, Error>;
|
|
||||||
///
|
///
|
||||||
/// #[inline]
|
/// fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
/// fn from_request(req: &HttpRequest<S>, _cfg: &Self::Config) -> Self::Result {
|
|
||||||
/// if rand::random() {
|
/// if rand::random() {
|
||||||
/// Ok(Thing { name: "thingy".into() })
|
/// Ok(Thing { name: "thingy".into() })
|
||||||
/// } else {
|
/// } else {
|
||||||
@ -747,18 +776,18 @@ where
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// extract text data from request
|
/// /// extract `Thing` from request
|
||||||
/// fn index(supplied_thing: Option<Thing>) -> Result<String> {
|
/// fn index(supplied_thing: Option<Thing>) -> String {
|
||||||
/// match supplied_thing {
|
/// match supplied_thing {
|
||||||
/// // Puns not intended
|
/// // Puns not intended
|
||||||
/// Some(thing) => Ok(format!("Got something: {:?}", thing)),
|
/// Some(thing) => format!("Got something: {:?}", thing),
|
||||||
/// None => Ok(format!("No thing!"))
|
/// None => format!("No thing!")
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource("/users/:first", |r| {
|
/// let app = App::new().resource("/users/:first", |r| {
|
||||||
/// r.method(http::Method::POST).with(index)
|
/// r.route(web::post().to(index))
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -773,7 +802,7 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
Box::new(T::from_request(req).then(|r| match r {
|
Box::new(T::from_request(req).into_future().then(|r| match r {
|
||||||
Ok(v) => future::ok(Some(v)),
|
Ok(v) => future::ok(Some(v)),
|
||||||
Err(_) => future::ok(None),
|
Err(_) => future::ok(None),
|
||||||
}))
|
}))
|
||||||
@ -782,46 +811,46 @@ where
|
|||||||
|
|
||||||
/// Optionally extract a field from the request or extract the Error if unsuccessful
|
/// Optionally extract a field from the request or extract the Error if unsuccessful
|
||||||
///
|
///
|
||||||
/// If the FromRequest for T fails, inject Err into handler rather than returning an error response
|
/// If the `FromRequest` for T fails, inject Err into handler rather than returning an error response
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # #[macro_use] extern crate serde_derive;
|
||||||
/// extern crate rand;
|
/// use actix_web::{web, App, Result, Error, FromRequest, ServiceFromRequest};
|
||||||
/// #[macro_use] extern crate serde_derive;
|
|
||||||
/// use actix_web::{http, App, Result, HttpRequest, Error, FromRequest};
|
|
||||||
/// use actix_web::error::ErrorBadRequest;
|
/// use actix_web::error::ErrorBadRequest;
|
||||||
|
/// use rand;
|
||||||
///
|
///
|
||||||
/// #[derive(Debug, Deserialize)]
|
/// #[derive(Debug, Deserialize)]
|
||||||
/// struct Thing { name: String }
|
/// struct Thing {
|
||||||
|
/// name: String
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// impl FromRequest for Thing {
|
/// impl<P> FromRequest<P> for Thing {
|
||||||
|
/// type Error = Error;
|
||||||
|
/// type Future = Result<Thing, Error>;
|
||||||
/// type Config = ();
|
/// type Config = ();
|
||||||
/// type Result = Result<Thing, Error>;
|
|
||||||
///
|
///
|
||||||
/// #[inline]
|
/// fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
/// fn from_request(req: &Request, _cfg: &Self::Config) -> Self::Result {
|
|
||||||
/// if rand::random() {
|
/// if rand::random() {
|
||||||
/// Ok(Thing { name: "thingy".into() })
|
/// Ok(Thing { name: "thingy".into() })
|
||||||
/// } else {
|
/// } else {
|
||||||
/// Err(ErrorBadRequest("no luck"))
|
/// Err(ErrorBadRequest("no luck"))
|
||||||
/// }
|
/// }
|
||||||
///
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// extract text data from request
|
/// /// extract `Thing` from request
|
||||||
/// fn index(supplied_thing: Result<Thing>) -> Result<String> {
|
/// fn index(supplied_thing: Result<Thing>) -> String {
|
||||||
/// match supplied_thing {
|
/// match supplied_thing {
|
||||||
/// Ok(thing) => Ok(format!("Got thing: {:?}", thing)),
|
/// Ok(thing) => format!("Got thing: {:?}", thing),
|
||||||
/// Err(e) => Ok(format!("Error extracting thing: {}", e))
|
/// Err(e) => format!("Error extracting thing: {}", e)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource("/users/:first", |r| {
|
/// let app = App::new().resource("/users/:first", |r| {
|
||||||
/// r.method(http::Method::POST).with(index)
|
/// r.route(web::post().to(index))
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -837,7 +866,7 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
Box::new(T::from_request(req).then(|res| match res {
|
Box::new(T::from_request(req).into_future().then(|res| match res {
|
||||||
Ok(v) => ok(Ok(v)),
|
Ok(v) => ok(Ok(v)),
|
||||||
Err(e) => ok(Err(e)),
|
Err(e) => ok(Err(e)),
|
||||||
}))
|
}))
|
||||||
@ -924,7 +953,7 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
|||||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
|
||||||
$fut_type {
|
$fut_type {
|
||||||
items: <($(Option<$T>,)+)>::default(),
|
items: <($(Option<$T>,)+)>::default(),
|
||||||
futs: ($($T::from_request(req),)+),
|
futs: ($($T::from_request(req).into_future(),)+),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -932,7 +961,7 @@ macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct $fut_type<P, $($T: FromRequest<P>),+> {
|
pub struct $fut_type<P, $($T: FromRequest<P>),+> {
|
||||||
items: ($(Option<$T>,)+),
|
items: ($(Option<$T>,)+),
|
||||||
futs: ($($T::Future,)+),
|
futs: ($(<$T::Future as futures::IntoFuture>::Future,)+),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P, $($T: FromRequest<P>),+> Future for $fut_type<P, $($T),+>
|
impl<P, $($T: FromRequest<P>),+> Future for $fut_type<P, $($T),+>
|
@ -7,55 +7,11 @@ use actix_service::{NewService, Service, Void};
|
|||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
use futures::{try_ready, Async, Future, IntoFuture, Poll};
|
use futures::{try_ready, Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
|
use crate::extract::FromRequest;
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||||
|
|
||||||
/// Trait implemented by types that can be extracted from request.
|
|
||||||
///
|
|
||||||
/// Types that implement this trait can be used with `Route` handlers.
|
|
||||||
pub trait FromRequest<P>: Sized {
|
|
||||||
/// The associated error which can be returned.
|
|
||||||
type Error: Into<Error>;
|
|
||||||
|
|
||||||
/// Future that resolves to a Self
|
|
||||||
type Future: Future<Item = Self, Error = Self::Error>;
|
|
||||||
|
|
||||||
/// Configuration for the extractor
|
|
||||||
type Config: ExtractorConfig;
|
|
||||||
|
|
||||||
/// Convert request to a Self
|
|
||||||
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Storage for extractor configs
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ConfigStorage {
|
|
||||||
pub(crate) storage: Option<Rc<Extensions>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigStorage {
|
|
||||||
pub fn store<C: ExtractorConfig>(&mut self, config: C) {
|
|
||||||
if self.storage.is_none() {
|
|
||||||
self.storage = Some(Rc::new(Extensions::new()));
|
|
||||||
}
|
|
||||||
if let Some(ref mut ext) = self.storage {
|
|
||||||
Rc::get_mut(ext).unwrap().insert(config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ExtractorConfig: Default + Clone + 'static {
|
|
||||||
/// Set default configuration to config storage
|
|
||||||
fn store_default(ext: &mut ConfigStorage) {
|
|
||||||
ext.store(Self::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtractorConfig for () {
|
|
||||||
fn store_default(_: &mut ConfigStorage) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handler converter factory
|
/// Handler converter factory
|
||||||
pub trait Factory<T, R>: Clone
|
pub trait Factory<T, R>: Clone
|
||||||
where
|
where
|
||||||
@ -134,14 +90,14 @@ where
|
|||||||
type Request = (T, HttpRequest);
|
type Request = (T, HttpRequest);
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = Void;
|
type Error = Void;
|
||||||
type Future = HandleServiceResponse<R::Future>;
|
type Future = HandleServiceResponse<<R::Future as IntoFuture>::Future>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
Ok(Async::Ready(()))
|
Ok(Async::Ready(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future {
|
fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future {
|
||||||
let fut = self.hnd.call(param).respond_to(&req);
|
let fut = self.hnd.call(param).respond_to(&req).into_future();
|
||||||
HandleServiceResponse {
|
HandleServiceResponse {
|
||||||
fut,
|
fut,
|
||||||
req: Some(req),
|
req: Some(req),
|
||||||
@ -368,7 +324,7 @@ impl<P, T: FromRequest<P>> Service for ExtractService<P, T> {
|
|||||||
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
|
||||||
let mut req = ServiceFromRequest::new(req, self.config.clone());
|
let mut req = ServiceFromRequest::new(req, self.config.clone());
|
||||||
ExtractResponse {
|
ExtractResponse {
|
||||||
fut: T::from_request(&mut req),
|
fut: T::from_request(&mut req).into_future(),
|
||||||
req: Some(req),
|
req: Some(req),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,7 +332,7 @@ impl<P, T: FromRequest<P>> Service for ExtractService<P, T> {
|
|||||||
|
|
||||||
pub struct ExtractResponse<P, T: FromRequest<P>> {
|
pub struct ExtractResponse<P, T: FromRequest<P>> {
|
||||||
req: Option<ServiceFromRequest<P>>,
|
req: Option<ServiceFromRequest<P>>,
|
||||||
fut: T::Future,
|
fut: <T::Future as IntoFuture>::Future,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P, T: FromRequest<P>> Future for ExtractResponse<P, T> {
|
impl<P, T: FromRequest<P>> Future for ExtractResponse<P, T> {
|
||||||
|
18
src/lib.rs
18
src/lib.rs
@ -1,7 +1,7 @@
|
|||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
pub mod extractor;
|
pub mod extract;
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
// mod info;
|
// mod info;
|
||||||
pub mod blocking;
|
pub mod blocking;
|
||||||
@ -17,23 +17,23 @@ pub mod test;
|
|||||||
|
|
||||||
// re-export for convenience
|
// re-export for convenience
|
||||||
pub use actix_http::Response as HttpResponse;
|
pub use actix_http::Response as HttpResponse;
|
||||||
pub use actix_http::{http, Error, HttpMessage, ResponseError};
|
pub use actix_http::{error, http, Error, HttpMessage, ResponseError, Result};
|
||||||
|
|
||||||
pub use crate::app::App;
|
pub use crate::app::App;
|
||||||
pub use crate::extractor::{Form, Json, Path, PayloadConfig, Query};
|
pub use crate::extract::{FromRequest, Json};
|
||||||
pub use crate::handler::FromRequest;
|
|
||||||
pub use crate::request::HttpRequest;
|
pub use crate::request::HttpRequest;
|
||||||
pub use crate::resource::Resource;
|
pub use crate::resource::Resource;
|
||||||
pub use crate::responder::{Either, Responder};
|
pub use crate::responder::{Either, Responder};
|
||||||
pub use crate::route::Route;
|
pub use crate::route::Route;
|
||||||
pub use crate::service::{ServiceRequest, ServiceResponse};
|
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||||
pub use crate::state::State;
|
pub use crate::state::State;
|
||||||
|
|
||||||
pub mod web {
|
pub mod web {
|
||||||
use actix_http::{http::Method, Error, Response};
|
use actix_http::{http::Method, Error, Response};
|
||||||
use futures::IntoFuture;
|
use futures::IntoFuture;
|
||||||
|
|
||||||
use crate::handler::{AsyncFactory, Factory, FromRequest};
|
use crate::extract::FromRequest;
|
||||||
|
use crate::handler::{AsyncFactory, Factory};
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::Route;
|
use crate::Route;
|
||||||
|
|
||||||
@ -107,9 +107,3 @@ pub mod web {
|
|||||||
Route::new().to_async(handler)
|
Route::new().to_async(handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod dev {
|
|
||||||
pub use crate::app::AppRouter;
|
|
||||||
pub use crate::handler::{AsyncFactory, Extract, Factory, Handle};
|
|
||||||
// pub use crate::info::ConnectionInfo;
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@ use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead};
|
|||||||
use actix_router::{Path, Url};
|
use actix_router::{Path, Url};
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
|
|
||||||
use crate::handler::FromRequest;
|
use crate::extract::FromRequest;
|
||||||
use crate::service::ServiceFromRequest;
|
use crate::service::ServiceFromRequest;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -9,7 +9,8 @@ use actix_service::{
|
|||||||
use futures::future::{ok, Either, FutureResult};
|
use futures::future::{ok, Either, FutureResult};
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::handler::{AsyncFactory, Factory, FromRequest};
|
use crate::extract::FromRequest;
|
||||||
|
use crate::handler::{AsyncFactory, Factory};
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::route::{CreateRouteService, Route, RouteService};
|
use crate::route::{CreateRouteService, Route, RouteService};
|
||||||
use crate::service::{ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceRequest, ServiceResponse};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use actix_http::{dev::ResponseBuilder, http::StatusCode, Error, Response};
|
use actix_http::{dev::ResponseBuilder, http::StatusCode, Error, Response};
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::future::{err, ok, Either as EitherFuture, FutureResult};
|
use futures::future::{err, ok, Either as EitherFuture, FutureResult};
|
||||||
use futures::{Future, Poll};
|
use futures::{Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ pub trait Responder {
|
|||||||
type Error: Into<Error>;
|
type Error: Into<Error>;
|
||||||
|
|
||||||
/// The future response value.
|
/// The future response value.
|
||||||
type Future: Future<Item = Response, Error = Self::Error>;
|
type Future: IntoFuture<Item = Response, Error = Self::Error>;
|
||||||
|
|
||||||
/// Convert itself to `AsyncResult` or `Error`.
|
/// Convert itself to `AsyncResult` or `Error`.
|
||||||
fn respond_to(self, req: &HttpRequest) -> Self::Future;
|
fn respond_to(self, req: &HttpRequest) -> Self::Future;
|
||||||
@ -34,11 +34,14 @@ where
|
|||||||
T: Responder,
|
T: Responder,
|
||||||
{
|
{
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
type Future = EitherFuture<T::Future, FutureResult<Response, T::Error>>;
|
type Future = EitherFuture<
|
||||||
|
<T::Future as IntoFuture>::Future,
|
||||||
|
FutureResult<Response, T::Error>,
|
||||||
|
>;
|
||||||
|
|
||||||
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
||||||
match self {
|
match self {
|
||||||
Some(t) => EitherFuture::A(t.respond_to(req)),
|
Some(t) => EitherFuture::A(t.respond_to(req).into_future()),
|
||||||
None => EitherFuture::B(ok(Response::build(StatusCode::NOT_FOUND).finish())),
|
None => EitherFuture::B(ok(Response::build(StatusCode::NOT_FOUND).finish())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +53,16 @@ where
|
|||||||
E: Into<Error>,
|
E: Into<Error>,
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = EitherFuture<ResponseFuture<T::Future>, FutureResult<Response, Error>>;
|
type Future = EitherFuture<
|
||||||
|
ResponseFuture<<T::Future as IntoFuture>::Future>,
|
||||||
|
FutureResult<Response, Error>,
|
||||||
|
>;
|
||||||
|
|
||||||
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
||||||
match self {
|
match self {
|
||||||
Ok(val) => EitherFuture::A(ResponseFuture::new(val.respond_to(req))),
|
Ok(val) => {
|
||||||
|
EitherFuture::A(ResponseFuture::new(val.respond_to(req).into_future()))
|
||||||
|
}
|
||||||
Err(e) => EitherFuture::B(err(e.into())),
|
Err(e) => EitherFuture::B(err(e.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,34 +155,36 @@ impl Responder for BytesMut {
|
|||||||
|
|
||||||
/// Combines two different responder types into a single type
|
/// Combines two different responder types into a single type
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # use futures::future::{ok, Future};
|
||||||
/// # extern crate futures;
|
/// use actix_web::{Either, Error, HttpResponse};
|
||||||
/// # use futures::future::Future;
|
|
||||||
/// use actix_web::{AsyncResponder, Either, Error, Request, Response};
|
|
||||||
/// use futures::future::result;
|
|
||||||
///
|
///
|
||||||
/// type RegisterResult =
|
/// type RegisterResult =
|
||||||
/// Either<Response, Box<Future<Item = Response, Error = Error>>>;
|
/// Either<HttpResponse, Box<Future<Item = HttpResponse, Error = Error>>>;
|
||||||
///
|
///
|
||||||
/// fn index(req: Request) -> RegisterResult {
|
/// fn index() -> RegisterResult {
|
||||||
/// if is_a_variant() {
|
/// if is_a_variant() {
|
||||||
/// // <- choose variant A
|
/// // <- choose left variant
|
||||||
/// Either::A(Response::BadRequest().body("Bad data"))
|
/// Either::A(HttpResponse::BadRequest().body("Bad data"))
|
||||||
/// } else {
|
/// } else {
|
||||||
/// Either::B(
|
/// Either::B(
|
||||||
/// // <- variant B
|
/// // <- Right variant
|
||||||
/// result(Ok(Response::Ok()
|
/// Box::new(ok(HttpResponse::Ok()
|
||||||
/// .content_type("text/html")
|
/// .content_type("text/html")
|
||||||
/// .body("Hello!")))
|
/// .body("Hello!")))
|
||||||
/// .responder(),
|
|
||||||
/// )
|
/// )
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// # fn is_a_variant() -> bool { true }
|
/// # fn is_a_variant() -> bool { true }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
pub type Either<A, B> = either::Either<A, B>;
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Either<A, B> {
|
||||||
|
/// First branch of the type
|
||||||
|
A(A),
|
||||||
|
/// Second branch of the type
|
||||||
|
B(B),
|
||||||
|
}
|
||||||
|
|
||||||
impl<A, B> Responder for Either<A, B>
|
impl<A, B> Responder for Either<A, B>
|
||||||
where
|
where
|
||||||
@ -182,12 +192,15 @@ where
|
|||||||
B: Responder,
|
B: Responder,
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = EitherResponder<A::Future, B::Future>;
|
type Future = EitherResponder<
|
||||||
|
<A::Future as IntoFuture>::Future,
|
||||||
|
<B::Future as IntoFuture>::Future,
|
||||||
|
>;
|
||||||
|
|
||||||
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
||||||
match self {
|
match self {
|
||||||
either::Either::Left(a) => EitherResponder::A(a.respond_to(req)),
|
Either::A(a) => EitherResponder::A(a.respond_to(req).into_future()),
|
||||||
either::Either::Right(b) => EitherResponder::B(b.respond_to(req)),
|
Either::B(b) => EitherResponder::B(b.respond_to(req).into_future()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +247,7 @@ where
|
|||||||
let req = req.clone();
|
let req = req.clone();
|
||||||
Box::new(
|
Box::new(
|
||||||
self.map_err(|e| e.into())
|
self.map_err(|e| e.into())
|
||||||
.and_then(move |r| ResponseFuture(r.respond_to(&req))),
|
.and_then(move |r| ResponseFuture(r.respond_to(&req).into_future())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
src/route.rs
18
src/route.rs
@ -5,11 +5,9 @@ use actix_http::{http::Method, Error, Extensions, Response};
|
|||||||
use actix_service::{NewService, Service};
|
use actix_service::{NewService, Service};
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
|
use crate::extract::{ConfigStorage, ExtractorConfig, FromRequest};
|
||||||
use crate::guard::{self, Guard};
|
use crate::guard::{self, Guard};
|
||||||
use crate::handler::{
|
use crate::handler::{AsyncFactory, AsyncHandle, Extract, Factory, Handle};
|
||||||
AsyncFactory, AsyncHandle, ConfigStorage, Extract, ExtractorConfig, Factory,
|
|
||||||
FromRequest, Handle,
|
|
||||||
};
|
|
||||||
use crate::responder::Responder;
|
use crate::responder::Responder;
|
||||||
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||||
use crate::HttpResponse;
|
use crate::HttpResponse;
|
||||||
@ -219,7 +217,7 @@ impl<P: 'static> Route<P> {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{web, http, App, Path};
|
/// use actix_web::{web, http, App, extract::Path};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
@ -244,7 +242,7 @@ impl<P: 'static> Route<P> {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::collections::HashMap;
|
/// # use std::collections::HashMap;
|
||||||
/// # use serde_derive::Deserialize;
|
/// # use serde_derive::Deserialize;
|
||||||
/// use actix_web::{web, http, App, Json, Path, Query};
|
/// use actix_web::{web, App, Json, extract::Path, extract::Query};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
@ -259,7 +257,7 @@ impl<P: 'static> Route<P> {
|
|||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource(
|
/// let app = App::new().resource(
|
||||||
/// "/{username}/index.html", // <- define path parameters
|
/// "/{username}/index.html", // <- define path parameters
|
||||||
/// |r| r.route(web::method(http::Method::GET).to(index)),
|
/// |r| r.route(web::get().to(index)),
|
||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -283,7 +281,7 @@ impl<P: 'static> Route<P> {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use futures::future::ok;
|
/// # use futures::future::ok;
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{web, http, App, Error, Path};
|
/// use actix_web::{web, App, Error, extract::Path};
|
||||||
/// use futures::Future;
|
/// use futures::Future;
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
@ -323,7 +321,7 @@ impl<P: 'static> Route<P> {
|
|||||||
/// for specific route.
|
/// for specific route.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use actix_web::{web, extractor, App};
|
/// use actix_web::{web, extract, App};
|
||||||
///
|
///
|
||||||
/// /// extract text data from request
|
/// /// extract text data from request
|
||||||
/// fn index(body: String) -> String {
|
/// fn index(body: String) -> String {
|
||||||
@ -335,7 +333,7 @@ impl<P: 'static> Route<P> {
|
|||||||
/// r.route(
|
/// r.route(
|
||||||
/// web::get()
|
/// web::get()
|
||||||
/// // limit size of the payload
|
/// // limit size of the payload
|
||||||
/// .config(extractor::PayloadConfig::new(4096))
|
/// .config(extract::PayloadConfig::new(4096))
|
||||||
/// // register handler
|
/// // register handler
|
||||||
/// .to(index)
|
/// .to(index)
|
||||||
/// )
|
/// )
|
||||||
|
@ -6,7 +6,7 @@ use actix_http::Extensions;
|
|||||||
use futures::future::{err, ok, FutureResult};
|
use futures::future::{err, ok, FutureResult};
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::handler::FromRequest;
|
use crate::extract::FromRequest;
|
||||||
use crate::service::ServiceFromRequest;
|
use crate::service::ServiceFromRequest;
|
||||||
|
|
||||||
/// Application state factory
|
/// Application state factory
|
||||||
|
@ -14,13 +14,10 @@ use crate::service::{ServiceFromRequest, ServiceRequest};
|
|||||||
/// Test `Request` builder
|
/// Test `Request` builder
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// # extern crate http;
|
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// # use http::{header, StatusCode};
|
|
||||||
/// # use actix_web::*;
|
/// # use actix_web::*;
|
||||||
/// use actix_web::test::TestRequest;
|
/// use actix_web::test::TestRequest;
|
||||||
///
|
///
|
||||||
/// fn index(req: &HttpRequest) -> HttpResponse {
|
/// fn index(req: HttpRequest) -> HttpResponse {
|
||||||
/// if let Some(hdr) = req.headers().get(header::CONTENT_TYPE) {
|
/// if let Some(hdr) = req.headers().get(header::CONTENT_TYPE) {
|
||||||
/// HttpResponse::Ok().into()
|
/// HttpResponse::Ok().into()
|
||||||
/// } else {
|
/// } else {
|
||||||
|
Loading…
Reference in New Issue
Block a user