From e50d4c5e0e7bcaaf50031ff1aaebc222910e3517 Mon Sep 17 00:00:00 2001
From: Nikolay Kim <fafhrd91@gmail.com>
Date: Sun, 3 Mar 2019 13:53:31 -0800
Subject: [PATCH] rename extractor module to extract, re-enable doc tests

---
 Cargo.toml                       |   1 -
 src/{extractor.rs => extract.rs} | 279 +++++++++++++++++--------------
 src/handler.rs                   |  54 +-----
 src/lib.rs                       |  18 +-
 src/request.rs                   |   2 +-
 src/resource.rs                  |   3 +-
 src/responder.rs                 |  61 ++++---
 src/route.rs                     |  18 +-
 src/state.rs                     |   2 +-
 src/test.rs                      |   5 +-
 10 files changed, 215 insertions(+), 228 deletions(-)
 rename src/{extractor.rs => extract.rs} (83%)

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<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)]
 /// 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<String> {
-///     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<Info>) -> Result<String> {
+/// /// extract `Info` from a path using serde
+/// fn index(info: Path<Info>) -> Result<String, Error> {
 ///     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<T> {
@@ -112,7 +150,7 @@ impl<T> Path<T> {
     }
 
     /// 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
         T: DeserializeOwned,
     {
@@ -158,13 +196,9 @@ impl<T: fmt::Display> fmt::Display for Path<T> {
 ///
 /// ## 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<T: fmt::Display> fmt::Display for Path<T> {
 ///    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<AuthRequest>) -> String {
+/// fn index(info: extract::Query<AuthRequest>) -> 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>(T);
@@ -253,21 +287,21 @@ impl<T: fmt::Display> fmt::Display for Query<T> {
 ///
 /// ## 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<FormData>) -> Result<String> {
-///     Ok(format!("Welcome {}!", form.username))
+/// fn index(form: Form<FormData>) -> String {
+///     format!("Welcome {}!", form.username)
 /// }
 /// # fn main() {}
 /// ```
@@ -333,19 +367,18 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
 
 /// 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<FormData>) -> Result<String> {
+/// /// Extract form data using serde.
+/// /// Custom configuration is used for this handler, max payload size is 4k
+/// fn index(form: extract::Form<FormData>) -> Result<String> {
 ///     Ok(format!("Welcome {}!", form.username))
 /// }
 ///
@@ -353,11 +386,11 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
 ///     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<Info>) -> Result<String> {
-///     Ok(format!("Welcome {}!", info.username))
+/// fn index(info: extract::Json<Info>) -> 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<Json<MyObj>> {
 ///     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<Info>) -> Result<String> {
-///     Ok(format!("Welcome {}!", info.username))
+/// fn index(info: Json<Info>) -> 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<String> {
-///     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<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.
 ///
@@ -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<String> {
-///     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<S> FromRequest<S> for Thing {
+/// impl<P> FromRequest<P> for Thing {
+///     type Error = Error;
+///     type Future = Result<Self, Self::Error>;
 ///     type Config = ();
-///     type Result = Result<Thing, Error>;
 ///
-///     #[inline]
-///     fn from_request(req: &HttpRequest<S>, _cfg: &Self::Config) -> Self::Result {
+///     fn from_request(req: &mut ServiceFromRequest<P>) -> 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<Thing>) -> Result<String> {
+/// /// extract `Thing` from request
+/// fn index(supplied_thing: Option<Thing>) -> 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<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)),
             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<P> FromRequest<P> for Thing {
+///     type Error = Error;
+///     type Future = Result<Thing, Error>;
 ///     type Config = ();
-///     type Result = Result<Thing, Error>;
 ///
-///     #[inline]
-///     fn from_request(req: &Request, _cfg: &Self::Config) -> Self::Result {
+///     fn from_request(req: &mut ServiceFromRequest<P>) -> 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<Thing>) -> Result<String> {
+/// /// extract `Thing` from request
+/// fn index(supplied_thing: Result<Thing>) -> 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<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)),
             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 {
             $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<P, $($T: FromRequest<P>),+> {
         items: ($(Option<$T>,)+),
-        futs: ($($T::Future,)+),
+        futs: ($(<$T::Future as futures::IntoFuture>::Future,)+),
     }
 
     impl<P, $($T: FromRequest<P>),+> Future for $fut_type<P, $($T),+>
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<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
 pub trait Factory<T, R>: Clone
 where
@@ -134,14 +90,14 @@ where
     type Request = (T, HttpRequest);
     type Response = ServiceResponse;
     type Error = Void;
-    type Future = HandleServiceResponse<R::Future>;
+    type Future = HandleServiceResponse<<R::Future as IntoFuture>::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<P, T: FromRequest<P>> Service for ExtractService<P, T> {
     fn call(&mut self, req: ServiceRequest<P>) -> 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<P, T: FromRequest<P>> Service for ExtractService<P, T> {
 
 pub struct ExtractResponse<P, T: FromRequest<P>> {
     req: Option<ServiceFromRequest<P>>,
-    fut: T::Future,
+    fut: <T::Future as IntoFuture>::Future,
 }
 
 impl<P, T: FromRequest<P>> Future for ExtractResponse<P, T> {
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<Error>;
 
     /// 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`.
     fn respond_to(self, req: &HttpRequest) -> Self::Future;
@@ -34,11 +34,14 @@ where
     T: Responder,
 {
     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 {
         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<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 {
         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<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() {
-///         // <- 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<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>
 where
@@ -182,12 +192,15 @@ where
     B: Responder,
 {
     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 {
         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<P: 'static> Route<P> {
     ///
     /// ```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<P: 'static> Route<P> {
     /// ```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<P: 'static> Route<P> {
     /// 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<P: 'static> Route<P> {
     /// ```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<P: 'static> Route<P> {
     /// 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<P: 'static> Route<P> {
     ///         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 {