diff --git a/src/extractor.rs b/src/de.rs similarity index 89% rename from src/extractor.rs rename to src/de.rs index 1eca75ce..a58277a9 100644 --- a/src/extractor.rs +++ b/src/de.rs @@ -2,29 +2,12 @@ use std::ops::{Deref, DerefMut}; use serde_urlencoded; use serde::de::{self, Deserializer, DeserializeOwned, Visitor, Error as DeError}; -use futures::future::{Future, FutureResult, result}; +use futures::future::{FutureResult, result}; use error::Error; +use handler::FromRequest; use httprequest::HttpRequest; - -pub trait HttpRequestExtractor: Sized where S: 'static -{ - type Result: Future; - - fn extract(req: &HttpRequest) -> Self::Result; -} - -impl HttpRequestExtractor for HttpRequest -{ - type Result = FutureResult; - - #[inline] - fn extract(req: &HttpRequest) -> Self::Result { - result(Ok(req.clone())) - } -} - /// Extract typed information from the request's path. /// /// `S` - application state type @@ -98,15 +81,15 @@ impl Path { } -impl HttpRequestExtractor for Path +impl FromRequest for Path where T: DeserializeOwned, S: 'static { type Result = FutureResult; #[inline] - fn extract(req: &HttpRequest) -> Self::Result { + fn from_request(req: &HttpRequest) -> Self::Result { let req = req.clone(); - result(de::Deserialize::deserialize(PathExtractor{req: &req}) + result(de::Deserialize::deserialize(PathDeserializer{req: &req}) .map_err(|e| e.into()) .map(|item| Path{item, req})) } @@ -185,13 +168,13 @@ impl Query { } } -impl HttpRequestExtractor for Query +impl FromRequest for Query where T: de::DeserializeOwned, S: 'static { type Result = FutureResult; #[inline] - fn extract(req: &HttpRequest) -> Self::Result { + fn from_request(req: &HttpRequest) -> Self::Result { let req = req.clone(); result(serde_urlencoded::from_str::(req.query_string()) .map_err(|e| e.into()) @@ -209,11 +192,11 @@ macro_rules! unsupported_type { }; } -pub struct PathExtractor<'de, S: 'de> { +pub struct PathDeserializer<'de, S: 'de> { req: &'de HttpRequest } -impl<'de, S: 'de> Deserializer<'de> for PathExtractor<'de, S> +impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { type Error = de::value::Error; @@ -305,7 +288,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathExtractor<'de, S> #[cfg(test)] mod tests { - use futures::Async; + use futures::{Async, Future}; use super::*; use router::{Router, Pattern}; use resource::Resource; @@ -334,7 +317,7 @@ mod tests { let (router, _) = Router::new("", ServerSettings::default(), routes); assert!(router.recognize(&mut req).is_some()); - match Path::::extract(&req).poll().unwrap() { + match Path::::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.key, "name"); assert_eq!(s.value, "user1"); @@ -342,7 +325,7 @@ mod tests { _ => unreachable!(), } - match Path::<(String, String), _>::extract(&req).poll().unwrap() { + match Path::<(String, String), _>::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.0, "name"); assert_eq!(s.1, "user1"); @@ -350,7 +333,7 @@ mod tests { _ => unreachable!(), } - match Query::::extract(&req).poll().unwrap() { + match Query::::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.id, "test"); }, diff --git a/src/handler.rs b/src/handler.rs index 2475ed9f..ea42b1b5 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -30,6 +30,16 @@ pub trait Responder { fn respond_to(self, req: HttpRequest) -> Result; } +/// Trait implemented by types that can be extracted from request. +/// +/// Types that implement this trait can be used with `Route::with()` method. +pub trait FromRequest: Sized where S: 'static +{ + type Result: Future; + + fn from_request(req: &HttpRequest) -> Self::Result; +} + /// Combines two different responder types into a single type /// /// ```rust diff --git a/src/httprequest.rs b/src/httprequest.rs index e545d09a..902daacd 100644 --- a/src/httprequest.rs +++ b/src/httprequest.rs @@ -6,6 +6,7 @@ use std::borrow::Cow; use bytes::Bytes; use cookie::Cookie; use futures::{Async, Stream, Poll}; +use futures::future::{FutureResult, result}; use futures_cpupool::CpuPool; use failure; use url::{Url, form_urlencoded}; @@ -18,10 +19,11 @@ use info::ConnectionInfo; use param::Params; use router::Router; use payload::Payload; +use handler::FromRequest; use httpmessage::HttpMessage; use httpresponse::{HttpResponse, HttpResponseBuilder}; use server::helpers::SharedHttpInnerMessage; -use error::{UrlGenerationError, CookieParseError, PayloadError}; +use error::{Error, UrlGenerationError, CookieParseError, PayloadError}; pub struct HttpInnerMessage { @@ -461,6 +463,16 @@ impl Clone for HttpRequest { } } +impl FromRequest for HttpRequest +{ + type Result = FutureResult; + + #[inline] + fn from_request(req: &HttpRequest) -> Self::Result { + result(Ok(req.clone())) + } +} + impl Stream for HttpRequest { type Item = Bytes; type Error = PayloadError; diff --git a/src/json.rs b/src/json.rs index 44a97108..7cfabe89 100644 --- a/src/json.rs +++ b/src/json.rs @@ -10,11 +10,10 @@ use serde::Serialize; use serde::de::DeserializeOwned; use error::{Error, JsonPayloadError, PayloadError}; -use handler::Responder; +use handler::{Responder, FromRequest}; use httpmessage::HttpMessage; use httprequest::HttpRequest; use httpresponse::HttpResponse; -use extractor::HttpRequestExtractor; /// Json helper /// @@ -112,13 +111,13 @@ impl Responder for Json { } } -impl HttpRequestExtractor for Json +impl FromRequest for Json where T: DeserializeOwned + 'static, S: 'static { type Result = Box>; #[inline] - fn extract(req: &HttpRequest) -> Self::Result { + fn from_request(req: &HttpRequest) -> Self::Result { Box::new( JsonBody::new(req.clone()) .from_err() diff --git a/src/lib.rs b/src/lib.rs index 88a690b8..d02e52e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,7 @@ extern crate tokio_openssl; mod application; mod body; mod context; +mod de; mod handler; mod httpmessage; mod httprequest; @@ -119,7 +120,6 @@ mod param; mod payload; mod pipeline; mod with; -mod extractor; pub mod client; pub mod fs; @@ -136,6 +136,7 @@ pub mod server; pub use error::{Error, Result, ResponseError}; pub use body::{Body, Binary}; pub use json::Json; +pub use de::{Path, Query}; pub use application::Application; pub use httpmessage::HttpMessage; pub use httprequest::HttpRequest; @@ -143,7 +144,6 @@ pub use httpresponse::HttpResponse; pub use handler::{Either, Responder, AsyncResponder, FutureResponse}; pub use context::HttpContext; pub use server::HttpServer; -pub use extractor::{Path, Query}; // re-exports pub use http::{Method, StatusCode}; @@ -172,14 +172,13 @@ pub mod dev { pub use body::BodyStream; pub use context::Drain; pub use info::ConnectionInfo; - pub use handler::{Handler, Reply}; + pub use handler::{Handler, Reply, FromRequest}; pub use route::Route; pub use resource::Resource; pub use with::WithHandler; pub use json::JsonBody; pub use router::{Router, Pattern}; pub use param::{FromParam, Params}; - pub use extractor::HttpRequestExtractor; pub use httpmessage::{UrlEncoded, MessageBody}; pub use httpresponse::HttpResponseBuilder; } diff --git a/src/resource.rs b/src/resource.rs index cb0963e3..b3c07f4e 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -7,12 +7,11 @@ use http::{Method, StatusCode}; use pred; use body::Body; use route::Route; -use handler::{Reply, Handler, Responder}; +use handler::{Reply, Handler, Responder, FromRequest}; use middleware::Middleware; use httprequest::HttpRequest; use httpresponse::HttpResponse; use with::WithHandler; -use extractor::HttpRequestExtractor; /// *Resource* is an entry in route table which corresponds to requested URL. /// @@ -143,7 +142,7 @@ impl Resource { /// ``` pub fn with(&mut self, handler: H) where H: WithHandler, - T: HttpRequestExtractor + 'static, + T: FromRequest + 'static, { self.routes.push(Route::default()); self.routes.last_mut().unwrap().with(handler) diff --git a/src/route.rs b/src/route.rs index 6f1f4192..75c5c60a 100644 --- a/src/route.rs +++ b/src/route.rs @@ -5,14 +5,13 @@ use futures::{Async, Future, Poll}; use error::Error; use pred::Predicate; -use handler::{Reply, ReplyItem, Handler, +use handler::{Reply, ReplyItem, Handler, FromRequest, Responder, RouteHandler, AsyncHandler, WrapHandler}; use middleware::{Middleware, Response as MiddlewareResponse, Started as MiddlewareStarted}; use httpcodes::HttpNotFound; use httprequest::HttpRequest; use httpresponse::HttpResponse; use with::{with, with2, with3, WithHandler}; -use extractor::HttpRequestExtractor; /// Resource route definition /// @@ -132,7 +131,7 @@ impl Route { /// ``` pub fn with(&mut self, handler: H) where H: WithHandler, - T: HttpRequestExtractor + 'static, + T: FromRequest + 'static, { self.h(with(handler)) } @@ -171,8 +170,8 @@ impl Route { pub fn with2(&mut self, handler: F) where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, { self.h(with2(handler)) } @@ -181,9 +180,9 @@ impl Route { pub fn with3(&mut self, handler: F) where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, - T3: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, + T3: FromRequest + 'static, { self.h(with3(handler)) } diff --git a/src/with.rs b/src/with.rs index 132a252a..ea73eaaf 100644 --- a/src/with.rs +++ b/src/with.rs @@ -4,16 +4,15 @@ use std::marker::PhantomData; use futures::{Async, Future, Poll}; use error::Error; -use handler::{Handler, Reply, ReplyItem, Responder}; +use handler::{Handler, FromRequest, Reply, ReplyItem, Responder}; use httprequest::HttpRequest; use httpresponse::HttpResponse; -use extractor::HttpRequestExtractor; /// Trait defines object that could be registered as route handler #[allow(unused_variables)] pub trait WithHandler: 'static - where T: HttpRequestExtractor, S: 'static + where T: FromRequest, S: 'static { /// The type of value that handler will return. type Result: Responder; @@ -26,7 +25,7 @@ pub trait WithHandler: 'static impl WithHandler for F where F: Fn(T) -> R + 'static, R: Responder + 'static, - T: HttpRequestExtractor, + T: FromRequest, S: 'static, { type Result = R; @@ -39,14 +38,14 @@ impl WithHandler for F pub(crate) fn with(h: H) -> With where H: WithHandler, - T: HttpRequestExtractor, + T: FromRequest, { With{hnd: Rc::new(UnsafeCell::new(h)), _t: PhantomData, _s: PhantomData} } pub struct With where H: WithHandler + 'static, - T: HttpRequestExtractor, + T: FromRequest, S: 'static, { hnd: Rc>, @@ -56,7 +55,7 @@ pub struct With impl Handler for With where H: WithHandler, - T: HttpRequestExtractor + 'static, + T: FromRequest + 'static, S: 'static, H: 'static { type Result = Reply; @@ -80,7 +79,7 @@ impl Handler for With struct WithHandlerFut where H: WithHandler, - T: HttpRequestExtractor, + T: FromRequest, T: 'static, S: 'static { started: bool, @@ -92,7 +91,7 @@ struct WithHandlerFut impl Future for WithHandlerFut where H: WithHandler, - T: HttpRequestExtractor + 'static, + T: FromRequest + 'static, S: 'static { type Item = HttpResponse; @@ -105,7 +104,7 @@ impl Future for WithHandlerFut let item = if !self.started { self.started = true; - let mut fut = T::extract(&self.req); + let mut fut = T::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item)) => item, Ok(Async::NotReady) => { @@ -140,8 +139,8 @@ pub(crate) fn with2(h: F) -> With2 where F: Fn(T1, T2) -> R, R: Responder, - T1: HttpRequestExtractor, - T2: HttpRequestExtractor, + T1: FromRequest, + T2: FromRequest, { With2{hnd: Rc::new(UnsafeCell::new(h)), _t1: PhantomData, _t2: PhantomData, _s: PhantomData} @@ -150,8 +149,8 @@ fn with2(h: F) -> With2 pub struct With2 where F: Fn(T1, T2) -> R, R: Responder, - T1: HttpRequestExtractor, - T2: HttpRequestExtractor, + T1: FromRequest, + T2: FromRequest, S: 'static, { hnd: Rc>, @@ -163,8 +162,8 @@ pub struct With2 impl Handler for With2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, S: 'static { type Result = Reply; @@ -190,8 +189,8 @@ impl Handler for With2 struct WithHandlerFut2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, S: 'static { started: bool, @@ -206,8 +205,8 @@ struct WithHandlerFut2 impl Future for WithHandlerFut2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, S: 'static { type Item = HttpResponse; @@ -220,10 +219,10 @@ impl Future for WithHandlerFut2 if !self.started { self.started = true; - let mut fut = T1::extract(&self.req); + let mut fut = T1::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item1)) => { - let mut fut = T2::extract(&self.req); + let mut fut = T2::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item2)) => { let hnd: &mut F = unsafe{&mut *self.hnd.get()}; @@ -262,7 +261,7 @@ impl Future for WithHandlerFut2 Async::Ready(item) => { self.item = Some(item); self.fut1.take(); - self.fut2 = Some(Box::new(T2::extract(&self.req))); + self.fut2 = Some(Box::new(T2::from_request(&self.req))); }, Async::NotReady => return Ok(Async::NotReady), } @@ -294,9 +293,9 @@ pub(crate) fn with3(h: F) -> With3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder, - T1: HttpRequestExtractor, - T2: HttpRequestExtractor, - T3: HttpRequestExtractor, + T1: FromRequest, + T2: FromRequest, + T3: FromRequest, { With3{hnd: Rc::new(UnsafeCell::new(h)), _s: PhantomData, _t1: PhantomData, _t2: PhantomData, _t3: PhantomData} @@ -305,9 +304,9 @@ fn with3(h: F) -> With3 pub struct With3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor, - T2: HttpRequestExtractor, - T3: HttpRequestExtractor, + T1: FromRequest, + T2: FromRequest, + T3: FromRequest, S: 'static, { hnd: Rc>, @@ -320,9 +319,9 @@ pub struct With3 impl Handler for With3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor, - T2: HttpRequestExtractor, - T3: HttpRequestExtractor, + T1: FromRequest, + T2: FromRequest, + T3: FromRequest, T1: 'static, T2: 'static, T3: 'static, S: 'static { type Result = Reply; @@ -350,9 +349,9 @@ impl Handler for With3 struct WithHandlerFut3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, - T3: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, + T3: FromRequest + 'static, S: 'static { hnd: Rc>, @@ -369,9 +368,9 @@ struct WithHandlerFut3 impl Future for WithHandlerFut3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, - T1: HttpRequestExtractor + 'static, - T2: HttpRequestExtractor + 'static, - T3: HttpRequestExtractor + 'static, + T1: FromRequest + 'static, + T2: FromRequest + 'static, + T3: FromRequest + 'static, S: 'static { type Item = HttpResponse; @@ -384,13 +383,13 @@ impl Future for WithHandlerFut3 if !self.started { self.started = true; - let mut fut = T1::extract(&self.req); + let mut fut = T1::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item1)) => { - let mut fut = T2::extract(&self.req); + let mut fut = T2::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item2)) => { - let mut fut = T3::extract(&self.req); + let mut fut = T3::from_request(&self.req); match fut.poll() { Ok(Async::Ready(item3)) => { let hnd: &mut F = unsafe{&mut *self.hnd.get()}; @@ -438,7 +437,7 @@ impl Future for WithHandlerFut3 Async::Ready(item) => { self.item1 = Some(item); self.fut1.take(); - self.fut2 = Some(Box::new(T2::extract(&self.req))); + self.fut2 = Some(Box::new(T2::from_request(&self.req))); }, Async::NotReady => return Ok(Async::NotReady), } @@ -449,7 +448,7 @@ impl Future for WithHandlerFut3 Async::Ready(item) => { self.item2 = Some(item); self.fut2.take(); - self.fut3 = Some(Box::new(T3::extract(&self.req))); + self.fut3 = Some(Box::new(T3::from_request(&self.req))); }, Async::NotReady => return Ok(Async::NotReady), }