diff --git a/Cargo.toml b/Cargo.toml index 30d23d02..03b1794f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ actix-router = { git = "https://github.com/actix/actix-net.git" } bytes = "0.4" derive_more = "0.14" -either = "1.5.1" encoding = "0.2" futures = "0.1" log = "0.4" diff --git a/src/extractor.rs b/src/extract.rs similarity index 83% rename from src/extractor.rs rename to src/extract.rs index 5fa9af61..d6e53327 100644 --- a/src/extractor.rs +++ b/src/extract.rs @@ -20,65 +20,103 @@ use actix_http::error::{ UrlencodedError, }; use actix_http::http::StatusCode; -use actix_http::{HttpMessage, Response}; +use actix_http::{Extensions, HttpMessage, Response}; use actix_router::PathDeserializer; -use crate::handler::{ConfigStorage, ExtractorConfig, FromRequest}; use crate::request::HttpRequest; use crate::responder::Responder; 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

: Sized { + /// The associated error which can be returned. + type Error: Into; + + /// Future that resolves to a Self + type Future: IntoFuture; + + /// Configuration for the extractor + type Config: ExtractorConfig; + + /// Convert request to a Self + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future; +} + +/// Storage for extractor configs +#[derive(Default)] +pub struct ConfigStorage { + pub(crate) storage: Option>, +} + +impl ConfigStorage { + pub fn store(&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)] /// Extract typed information from the request's path. /// /// ## Example /// -/// ```rust,ignore -/// # extern crate bytes; -/// # extern crate actix_web; -/// # extern crate futures; -/// use actix_web::{http, App, Path, Result}; +/// ```rust +/// use actix_web::{web, http, App, extract::Path}; /// /// /// extract path info from "/{username}/{count}/index.html" url /// /// {username} - deserializes to a String /// /// {count} - - deserializes to a u32 -/// fn index(info: Path<(String, u32)>) -> Result { -/// Ok(format!("Welcome {}! {}", info.0, info.1)) +/// fn index(info: Path<(String, u32)>) -> String { +/// format!("Welcome {}! {}", info.0, info.1) /// } /// /// fn main() { /// let app = App::new().resource( /// "/{username}/{count}/index.html", // <- define path parameters -/// |r| r.method(http::Method::GET).with(index), -/// ); // <- use `with` extractor +/// |r| r.route(web::get().to(index)) // <- register handler with `Path` extractor +/// ); /// } /// ``` /// /// It is possible to extract path information to a specific type that /// implements `Deserialize` trait from *serde*. /// -/// ```rust,ignore -/// # extern crate bytes; -/// # extern crate actix_web; -/// # extern crate futures; +/// ```rust /// #[macro_use] extern crate serde_derive; -/// use actix_web::{http, App, Path, Result}; +/// use actix_web::{web, App, extract::Path, Error}; /// /// #[derive(Deserialize)] /// struct Info { /// username: String, /// } /// -/// /// extract path info using serde -/// fn index(info: Path) -> Result { +/// /// extract `Info` from a path using serde +/// fn index(info: Path) -> Result { /// Ok(format!("Welcome {}!", info.username)) /// } /// /// fn main() { /// let app = App::new().resource( /// "/{username}/index.html", // <- define path parameters -/// |r| r.method(http::Method::GET).with(index), -/// ); // <- use `with` extractor +/// |r| r.route(web::get().to(index)) // <- use handler with Path` extractor +/// ); /// } /// ``` pub struct Path { @@ -112,7 +150,7 @@ impl Path { } /// Extract path information from a request - pub fn extract

(req: &ServiceFromRequest

) -> Result, de::value::Error> + pub fn extract(req: &HttpRequest) -> Result, de::value::Error> where T: DeserializeOwned, { @@ -158,13 +196,9 @@ impl fmt::Display for Path { /// /// ## Example /// -/// ```rust,ignore -/// # extern crate bytes; -/// # extern crate actix_web; -/// # extern crate futures; +/// ```rust /// #[macro_use] extern crate serde_derive; -/// use actix_web::{App, Query, http}; -/// +/// use actix_web::{web, extract, App}; /// ///#[derive(Debug, Deserialize)] ///pub enum ResponseType { @@ -178,17 +212,17 @@ impl fmt::Display for Path { /// response_type: ResponseType, ///} /// -/// // use `with` extractor for query info -/// // this handler get called only if request's query contains `username` field +/// // Use `Query` extractor for query information. +/// // 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"` -/// fn index(info: Query) -> String { +/// fn index(info: extract::Query) -> String { /// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type) /// } /// /// fn main() { /// let app = App::new().resource( /// "/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); @@ -253,21 +287,21 @@ impl fmt::Display for Query { /// /// ## Example /// -/// ```rust,ignore +/// ```rust /// # extern crate actix_web; /// #[macro_use] extern crate serde_derive; -/// use actix_web::{App, Form, Result}; +/// use actix_web::{web, App, extract::Form}; /// /// #[derive(Deserialize)] /// struct FormData { /// username: String, /// } /// -/// /// extract form data using serde -/// /// this handler get called only if content type is *x-www-form-urlencoded* +/// /// Extract form data using serde. +/// /// 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 -/// fn index(form: Form) -> Result { -/// Ok(format!("Welcome {}!", form.username)) +/// fn index(form: Form) -> String { +/// format!("Welcome {}!", form.username) /// } /// # fn main() {} /// ``` @@ -333,19 +367,18 @@ impl fmt::Display for Form { /// Form extractor configuration /// -/// ```rust,ignore -/// # extern crate actix_web; +/// ```rust /// #[macro_use] extern crate serde_derive; -/// use actix_web::{http, App, Form, Result}; +/// use actix_web::{web, extract, App, Result}; /// /// #[derive(Deserialize)] /// struct FormData { /// username: String, /// } /// -/// /// extract form data using serde. -/// /// custom configuration is used for this handler, max payload size is 4k -/// fn index(form: Form) -> Result { +/// /// Extract form data using serde. +/// /// Custom configuration is used for this handler, max payload size is 4k +/// fn index(form: extract::Form) -> Result { /// Ok(format!("Welcome {}!", form.username)) /// } /// @@ -353,11 +386,11 @@ impl fmt::Display for Form { /// let app = App::new().resource( /// "/index.html", /// |r| { -/// r.method(http::Method::GET) -/// // register form handler and change form extractor configuration -/// .with_config(index, |cfg| {cfg.0.limit(4096);}) -/// }, -/// ); +/// r.route(web::get() +/// // change `Form` extractor configuration +/// .config(extract::FormConfig::default().limit(4097)) +/// .to(index)) +/// }); /// } /// ``` #[derive(Clone)] @@ -408,10 +441,9 @@ impl Default for FormConfig { /// /// ## Example /// -/// ```rust,ignore -/// # extern crate actix_web; +/// ```rust /// #[macro_use] extern crate serde_derive; -/// use actix_web::{App, Json, Result, http}; +/// use actix_web::{web, extract, App}; /// /// #[derive(Deserialize)] /// struct Info { @@ -419,14 +451,14 @@ impl Default for FormConfig { /// } /// /// /// deserialize `Info` from request's body -/// fn index(info: Json) -> Result { -/// Ok(format!("Welcome {}!", info.username)) +/// fn index(info: extract::Json) -> String { +/// format!("Welcome {}!", info.username) /// } /// /// fn main() { /// let app = App::new().resource( /// "/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` /// trait from *serde*. /// -/// ```rust,ignore -/// # extern crate actix_web; +/// ```rust /// # #[macro_use] extern crate serde_derive; /// # use actix_web::*; /// # @@ -447,7 +478,7 @@ impl Default for FormConfig { /// /// fn index(req: HttpRequest) -> Result> { /// Ok(Json(MyObj { -/// name: req.match_info().query("name")?, +/// name: req.match_info().get("name").unwrap().to_string(), /// })) /// } /// # fn main() {} @@ -536,10 +567,9 @@ where /// Json extractor configuration /// -/// ```rust,ignore -/// # extern crate actix_web; +/// ```rust /// #[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)] /// struct Info { @@ -547,20 +577,20 @@ where /// } /// /// /// deserialize `Info` from request's body, max payload size is 4kb -/// fn index(info: Json) -> Result { -/// Ok(format!("Welcome {}!", info.username)) +/// fn index(info: Json) -> String { +/// format!("Welcome {}!", info.username) /// } /// /// fn main() { /// let app = App::new().resource("/index.html", |r| { -/// r.method(http::Method::POST) -/// .with_config(index, |cfg| { -/// cfg.0.limit(4096) // <- change json extractor configuration -/// .error_handler(|err, req| { // <- create custom error response -/// error::InternalError::from_response( -/// err, HttpResponse::Conflict().finish()).into() -/// }); -/// }) +/// r.route(web::post().config( +/// // change json extractor configuration +/// extract::JsonConfig::default().limit(4096) +/// .error_handler(|err, req| { // <- create custom error response +/// error::InternalError::from_response( +/// 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. /// @@ -607,19 +637,18 @@ impl Default for JsonConfig { /// /// ## Example /// -/// ```rust,ignore -/// extern crate bytes; -/// # extern crate actix_web; -/// use actix_web::{http, App, Result}; +/// ```rust +/// use bytes::Bytes; +/// use actix_web::{web, App}; /// -/// /// extract text data from request -/// fn index(body: bytes::Bytes) -> Result { -/// Ok(format!("Body {:?}!", body)) +/// /// extract binary data from request +/// fn index(body: Bytes) -> String { +/// format!("Body {:?}!", body) /// } /// /// fn main() { /// 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

FromRequest

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. /// @@ -653,21 +682,20 @@ where /// /// ## Example /// -/// ```rust,ignore -/// # extern crate actix_web; -/// use actix_web::{http, App, Result}; +/// ```rust +/// use actix_web::{web, extract, App}; /// /// /// extract text data from request -/// fn index(body: String) -> Result { -/// Ok(format!("Body {}!", body)) +/// fn index(text: String) -> String { +/// format!("Body {}!", text) /// } /// /// fn main() { /// let app = App::new().resource("/index.html", |r| { -/// r.method(http::Method::GET) -/// .with_config(index, |cfg| { // <- register handler with extractor params -/// cfg.0.limit(4096); // <- limit size of the payload -/// }) +/// r.route( +/// web::get() +/// .config(extract::PayloadConfig::new(4096)) // <- limit size of the payload +/// .to(index)) // <- register handler with extractor params /// }); /// } /// ``` @@ -722,22 +750,23 @@ where /// /// ## Example /// -/// ```rust,ignore -/// # extern crate actix_web; -/// extern crate rand; -/// #[macro_use] extern crate serde_derive; -/// use actix_web::{http, App, Result, HttpRequest, Error, FromRequest}; +/// ```rust +/// # #[macro_use] extern crate serde_derive; +/// use actix_web::{web, App, Error, FromRequest, ServiceFromRequest}; /// use actix_web::error::ErrorBadRequest; +/// use rand; /// /// #[derive(Debug, Deserialize)] -/// struct Thing { name: String } +/// struct Thing { +/// name: String +/// } /// -/// impl FromRequest for Thing { +/// impl

FromRequest

for Thing { +/// type Error = Error; +/// type Future = Result; /// type Config = (); -/// type Result = Result; /// -/// #[inline] -/// fn from_request(req: &HttpRequest, _cfg: &Self::Config) -> Self::Result { +/// fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { /// if rand::random() { /// Ok(Thing { name: "thingy".into() }) /// } else { @@ -747,18 +776,18 @@ where /// } /// } /// -/// /// extract text data from request -/// fn index(supplied_thing: Option) -> Result { +/// /// extract `Thing` from request +/// fn index(supplied_thing: Option) -> String { /// match supplied_thing { /// // Puns not intended -/// Some(thing) => Ok(format!("Got something: {:?}", thing)), -/// None => Ok(format!("No thing!")) +/// Some(thing) => format!("Got something: {:?}", thing), +/// None => format!("No thing!") /// } /// } /// /// fn main() { /// 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] fn from_request(req: &mut ServiceFromRequest

) -> 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)), Err(_) => future::ok(None), })) @@ -782,46 +811,46 @@ where /// 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 /// -/// ```rust,ignore -/// # extern crate actix_web; -/// extern crate rand; -/// #[macro_use] extern crate serde_derive; -/// use actix_web::{http, App, Result, HttpRequest, Error, FromRequest}; +/// ```rust +/// # #[macro_use] extern crate serde_derive; +/// use actix_web::{web, App, Result, Error, FromRequest, ServiceFromRequest}; /// use actix_web::error::ErrorBadRequest; +/// use rand; /// /// #[derive(Debug, Deserialize)] -/// struct Thing { name: String } +/// struct Thing { +/// name: String +/// } /// -/// impl FromRequest for Thing { +/// impl

FromRequest

for Thing { +/// type Error = Error; +/// type Future = Result; /// type Config = (); -/// type Result = Result; /// -/// #[inline] -/// fn from_request(req: &Request, _cfg: &Self::Config) -> Self::Result { +/// fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { /// if rand::random() { /// Ok(Thing { name: "thingy".into() }) /// } else { /// Err(ErrorBadRequest("no luck")) /// } -/// /// } /// } /// -/// /// extract text data from request -/// fn index(supplied_thing: Result) -> Result { +/// /// extract `Thing` from request +/// fn index(supplied_thing: Result) -> String { /// match supplied_thing { -/// Ok(thing) => Ok(format!("Got thing: {:?}", thing)), -/// Err(e) => Ok(format!("Error extracting thing: {}", e)) +/// Ok(thing) => format!("Got thing: {:?}", thing), +/// Err(e) => format!("Error extracting thing: {}", e) /// } /// } /// /// fn main() { /// 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] fn from_request(req: &mut ServiceFromRequest

) -> 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)), 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

) -> Self::Future { $fut_type { 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)] pub struct $fut_type),+> { items: ($(Option<$T>,)+), - futs: ($($T::Future,)+), + futs: ($(<$T::Future as futures::IntoFuture>::Future,)+), } impl),+> Future for $fut_type diff --git a/src/handler.rs b/src/handler.rs index 313422ed..98a36c56 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -7,55 +7,11 @@ use actix_service::{NewService, Service, Void}; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll}; +use crate::extract::FromRequest; use crate::request::HttpRequest; use crate::responder::Responder; 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

: Sized { - /// The associated error which can be returned. - type Error: Into; - - /// Future that resolves to a Self - type Future: Future; - - /// Configuration for the extractor - type Config: ExtractorConfig; - - /// Convert request to a Self - fn from_request(req: &mut ServiceFromRequest

) -> Self::Future; -} - -/// Storage for extractor configs -#[derive(Default)] -pub struct ConfigStorage { - pub(crate) storage: Option>, -} - -impl ConfigStorage { - pub fn store(&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 pub trait Factory: Clone where @@ -134,14 +90,14 @@ where type Request = (T, HttpRequest); type Response = ServiceResponse; type Error = Void; - type Future = HandleServiceResponse; + type Future = HandleServiceResponse<::Future>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } 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 { fut, req: Some(req), @@ -368,7 +324,7 @@ impl> Service for ExtractService { fn call(&mut self, req: ServiceRequest

) -> Self::Future { let mut req = ServiceFromRequest::new(req, self.config.clone()); ExtractResponse { - fut: T::from_request(&mut req), + fut: T::from_request(&mut req).into_future(), req: Some(req), } } @@ -376,7 +332,7 @@ impl> Service for ExtractService { pub struct ExtractResponse> { req: Option>, - fut: T::Future, + fut: ::Future, } impl> Future for ExtractResponse { diff --git a/src/lib.rs b/src/lib.rs index e876a7ea..f61bf0ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![allow(clippy::type_complexity)] mod app; -pub mod extractor; +pub mod extract; pub mod handler; // mod info; pub mod blocking; @@ -17,23 +17,23 @@ pub mod test; // re-export for convenience 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::extractor::{Form, Json, Path, PayloadConfig, Query}; -pub use crate::handler::FromRequest; +pub use crate::extract::{FromRequest, Json}; pub use crate::request::HttpRequest; pub use crate::resource::Resource; pub use crate::responder::{Either, Responder}; pub use crate::route::Route; -pub use crate::service::{ServiceRequest, ServiceResponse}; +pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; pub use crate::state::State; pub mod web { use actix_http::{http::Method, Error, Response}; use futures::IntoFuture; - use crate::handler::{AsyncFactory, Factory, FromRequest}; + use crate::extract::FromRequest; + use crate::handler::{AsyncFactory, Factory}; use crate::responder::Responder; use crate::Route; @@ -107,9 +107,3 @@ pub mod web { 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; -} diff --git a/src/request.rs b/src/request.rs index a7c84b53..48a2dd83 100644 --- a/src/request.rs +++ b/src/request.rs @@ -8,7 +8,7 @@ use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead}; use actix_router::{Path, Url}; use futures::future::{ok, FutureResult}; -use crate::handler::FromRequest; +use crate::extract::FromRequest; use crate::service::ServiceFromRequest; #[derive(Clone)] diff --git a/src/resource.rs b/src/resource.rs index 98c2dc11..f05e998f 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -9,7 +9,8 @@ use actix_service::{ use futures::future::{ok, Either, FutureResult}; 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::route::{CreateRouteService, Route, RouteService}; use crate::service::{ServiceRequest, ServiceResponse}; diff --git a/src/responder.rs b/src/responder.rs index b3ec7ec7..22588a9c 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -1,7 +1,7 @@ use actix_http::{dev::ResponseBuilder, http::StatusCode, Error, Response}; use bytes::{Bytes, BytesMut}; use futures::future::{err, ok, Either as EitherFuture, FutureResult}; -use futures::{Future, Poll}; +use futures::{Future, IntoFuture, Poll}; use crate::request::HttpRequest; @@ -13,7 +13,7 @@ pub trait Responder { type Error: Into; /// The future response value. - type Future: Future; + type Future: IntoFuture; /// Convert itself to `AsyncResult` or `Error`. fn respond_to(self, req: &HttpRequest) -> Self::Future; @@ -34,11 +34,14 @@ where T: Responder, { type Error = T::Error; - type Future = EitherFuture>; + type Future = EitherFuture< + ::Future, + FutureResult, + >; fn respond_to(self, req: &HttpRequest) -> Self::Future { 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())), } } @@ -50,11 +53,16 @@ where E: Into, { type Error = Error; - type Future = EitherFuture, FutureResult>; + type Future = EitherFuture< + ResponseFuture<::Future>, + FutureResult, + >; fn respond_to(self, req: &HttpRequest) -> Self::Future { 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())), } } @@ -147,34 +155,36 @@ impl Responder for BytesMut { /// Combines two different responder types into a single type /// -/// ```rust,ignore -/// # extern crate actix_web; -/// # extern crate futures; -/// # use futures::future::Future; -/// use actix_web::{AsyncResponder, Either, Error, Request, Response}; -/// use futures::future::result; +/// ```rust +/// # use futures::future::{ok, Future}; +/// use actix_web::{Either, Error, HttpResponse}; /// /// type RegisterResult = -/// Either>>; +/// Either>>; /// -/// fn index(req: Request) -> RegisterResult { +/// fn index() -> RegisterResult { /// if is_a_variant() { -/// // <- choose variant A -/// Either::A(Response::BadRequest().body("Bad data")) +/// // <- choose left variant +/// Either::A(HttpResponse::BadRequest().body("Bad data")) /// } else { /// Either::B( -/// // <- variant B -/// result(Ok(Response::Ok() +/// // <- Right variant +/// Box::new(ok(HttpResponse::Ok() /// .content_type("text/html") /// .body("Hello!"))) -/// .responder(), /// ) /// } /// } /// # fn is_a_variant() -> bool { true } /// # fn main() {} /// ``` -pub type Either = either::Either; +#[derive(Debug, PartialEq)] +pub enum Either { + /// First branch of the type + A(A), + /// Second branch of the type + B(B), +} impl Responder for Either where @@ -182,12 +192,15 @@ where B: Responder, { type Error = Error; - type Future = EitherResponder; + type Future = EitherResponder< + ::Future, + ::Future, + >; fn respond_to(self, req: &HttpRequest) -> Self::Future { match self { - either::Either::Left(a) => EitherResponder::A(a.respond_to(req)), - either::Either::Right(b) => EitherResponder::B(b.respond_to(req)), + Either::A(a) => EitherResponder::A(a.respond_to(req).into_future()), + Either::B(b) => EitherResponder::B(b.respond_to(req).into_future()), } } } @@ -234,7 +247,7 @@ where let req = req.clone(); Box::new( 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())), ) } } diff --git a/src/route.rs b/src/route.rs index 16a4fc5b..72abeb32 100644 --- a/src/route.rs +++ b/src/route.rs @@ -5,11 +5,9 @@ use actix_http::{http::Method, Error, Extensions, Response}; use actix_service::{NewService, Service}; use futures::{Async, Future, IntoFuture, Poll}; +use crate::extract::{ConfigStorage, ExtractorConfig, FromRequest}; use crate::guard::{self, Guard}; -use crate::handler::{ - AsyncFactory, AsyncHandle, ConfigStorage, Extract, ExtractorConfig, Factory, - FromRequest, Handle, -}; +use crate::handler::{AsyncFactory, AsyncHandle, Extract, Factory, Handle}; use crate::responder::Responder; use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; use crate::HttpResponse; @@ -219,7 +217,7 @@ impl Route

{ /// /// ```rust /// #[macro_use] extern crate serde_derive; - /// use actix_web::{web, http, App, Path}; + /// use actix_web::{web, http, App, extract::Path}; /// /// #[derive(Deserialize)] /// struct Info { @@ -244,7 +242,7 @@ impl Route

{ /// ```rust /// # use std::collections::HashMap; /// # 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)] /// struct Info { @@ -259,7 +257,7 @@ impl Route

{ /// fn main() { /// let app = App::new().resource( /// "/{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 Route

{ /// ```rust /// # use futures::future::ok; /// #[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; /// /// #[derive(Deserialize)] @@ -323,7 +321,7 @@ impl Route

{ /// for specific route. /// /// ```rust - /// use actix_web::{web, extractor, App}; + /// use actix_web::{web, extract, App}; /// /// /// extract text data from request /// fn index(body: String) -> String { @@ -335,7 +333,7 @@ impl Route

{ /// r.route( /// web::get() /// // limit size of the payload - /// .config(extractor::PayloadConfig::new(4096)) + /// .config(extract::PayloadConfig::new(4096)) /// // register handler /// .to(index) /// ) diff --git a/src/state.rs b/src/state.rs index 4a450245..168a8c89 100644 --- a/src/state.rs +++ b/src/state.rs @@ -6,7 +6,7 @@ use actix_http::Extensions; use futures::future::{err, ok, FutureResult}; use futures::{Async, Future, IntoFuture, Poll}; -use crate::handler::FromRequest; +use crate::extract::FromRequest; use crate::service::ServiceFromRequest; /// Application state factory diff --git a/src/test.rs b/src/test.rs index 4899cfe4..b4447f8b 100644 --- a/src/test.rs +++ b/src/test.rs @@ -14,13 +14,10 @@ use crate::service::{ServiceFromRequest, ServiceRequest}; /// Test `Request` builder /// /// ```rust,ignore -/// # extern crate http; -/// # extern crate actix_web; -/// # use http::{header, StatusCode}; /// # use actix_web::*; /// 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) { /// HttpResponse::Ok().into() /// } else {