diff --git a/README.md b/README.md index 869ee3a3f..e1482c27c 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Actix web is a simple, pragmatic, extremely fast, web framework for Rust. ```rust extern crate actix_web; -use actix_web::*; +use actix_web::{Application, HttpServer, Path}; fn index(info: Path<(String, u32)>) -> String { format!("Hello {}! id:{}", info.0, info.1) diff --git a/src/de.rs b/src/de.rs index 75d3e637e..96500e768 100644 --- a/src/de.rs +++ b/src/de.rs @@ -12,8 +12,6 @@ use httprequest::HttpRequest; /// Extract typed information from the request's path. /// -/// `S` - application state type -/// /// ## Example /// /// ```rust @@ -49,66 +47,48 @@ use httprequest::HttpRequest; /// # use actix_web::*; /// use actix_web::Path; /// -/// /// Application state -/// struct State {} -/// /// #[derive(Deserialize)] /// struct Info { /// username: String, /// } /// /// /// extract path info using serde -/// fn index(info: Path) -> Result { +/// fn index(info: Path) -> Result { /// Ok(format!("Welcome {}!", info.username)) /// } /// /// fn main() { -/// let app = Application::with_state(State{}).resource( +/// let app = Application::new().resource( /// "/{username}/index.html", // <- define path parameters /// |r| r.method(Method::GET).with(index)); // <- use `with` extractor /// } /// ``` -pub struct Path{ - item: T, - req: HttpRequest, +pub struct Path{ + inner: T } -impl Deref for Path { +impl Deref for Path { type Target = T; fn deref(&self) -> &T { - &self.item + &self.inner } } -impl DerefMut for Path { +impl DerefMut for Path { fn deref_mut(&mut self) -> &mut T { - &mut self.item + &mut self.inner } } -impl Path { - - /// Shared application state - #[inline] - pub fn state(&self) -> &S { - self.req.state() +impl Path { + /// Deconstruct to a inner value + pub fn into_inner(self) -> T { + self.inner } - - /// Incoming request - #[inline] - pub fn request(&self) -> &HttpRequest { - &self.req - } - - /// Deconstruct instance into parts - pub fn into(self) -> (T, HttpRequest) { - (self.item, self.req) - } - } -impl FromRequest for Path +impl FromRequest for Path where T: DeserializeOwned, S: 'static { type Result = FutureResult; @@ -118,14 +98,12 @@ impl FromRequest for Path let req = req.clone(); result(de::Deserialize::deserialize(PathDeserializer{req: &req}) .map_err(|e| e.into()) - .map(|item| Path{item, req})) + .map(|inner| Path{inner})) } } /// Extract typed information from from the request's query. /// -/// `S` - application state type -/// /// ## Example /// /// ```rust @@ -136,9 +114,6 @@ impl FromRequest for Path /// # use actix_web::*; /// use actix_web::Query; /// -/// /// Application state -/// struct State {} -/// /// #[derive(Deserialize)] /// struct Info { /// username: String, @@ -146,56 +121,40 @@ impl FromRequest for Path /// /// // use `with` extractor for query info /// // this handler get called only if request's query contains `username` field -/// fn index(info: Query) -> Result { +/// fn index(info: Query) -> Result { /// Ok(format!("Welcome {}!", info.username)) /// } /// /// fn main() { -/// let app = Application::with_state(State{}).resource( +/// let app = Application::new().resource( /// "/index.html", /// |r| r.method(Method::GET).with(index)); // <- use `with` extractor /// } /// ``` -pub struct Query{ - item: T, - req: HttpRequest, -} +pub struct Query(T); -impl Deref for Query { +impl Deref for Query { type Target = T; fn deref(&self) -> &T { - &self.item + &self.0 } } -impl DerefMut for Query { +impl DerefMut for Query { fn deref_mut(&mut self) -> &mut T { - &mut self.item + &mut self.0 } } -impl Query { - - /// Shared application state - #[inline] - pub fn state(&self) -> &S { - self.req.state() - } - - /// Incoming request - #[inline] - pub fn request(&self) -> &HttpRequest { - &self.req - } - - /// Deconstruct instance into parts - pub fn into(self) -> (T, HttpRequest) { - (self.item, self.req) +impl Query { + /// Deconstruct to a inner value + pub fn into_inner(self) -> T { + self.0 } } -impl FromRequest for Query +impl FromRequest for Query where T: de::DeserializeOwned, S: 'static { type Result = FutureResult; @@ -205,7 +164,7 @@ impl FromRequest for Query let req = req.clone(); result(serde_urlencoded::from_str::(req.query_string()) .map_err(|e| e.into()) - .map(|item| Query{ item, req})) + .map(Query)) } } @@ -581,7 +540,7 @@ mod tests { let (router, _) = Router::new("", ServerSettings::default(), routes); assert!(router.recognize(&mut req).is_some()); - match Path::::from_request(&req).poll().unwrap() { + match Path::::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.key, "name"); assert_eq!(s.value, "user1"); @@ -589,7 +548,7 @@ mod tests { _ => unreachable!(), } - match Path::<(String, String), _>::from_request(&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"); @@ -597,7 +556,7 @@ mod tests { _ => unreachable!(), } - match Query::::from_request(&req).poll().unwrap() { + match Query::::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.id, "test"); }, @@ -607,7 +566,7 @@ mod tests { let mut req = TestRequest::with_uri("/name/32/").finish(); assert!(router.recognize(&mut req).is_some()); - match Path::::from_request(&req).poll().unwrap() { + match Path::::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.key, "name"); assert_eq!(s.value, 32); @@ -615,7 +574,7 @@ mod tests { _ => unreachable!(), } - match Path::<(String, u8), _>::from_request(&req).poll().unwrap() { + match Path::<(String, u8)>::from_request(&req).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.0, "name"); assert_eq!(s.1, 32); diff --git a/src/handler.rs b/src/handler.rs index ea42b1b5f..32a3d99b2 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,5 +1,6 @@ +use std::ops::Deref; use std::marker::PhantomData; -use futures::future::{Future, ok, err}; +use futures::future::{Future, FutureResult, ok, err}; use error::Error; use httprequest::HttpRequest; @@ -347,3 +348,57 @@ impl RouteHandler for AsyncHandler Reply::async(fut) } } + + +/// Access to an application state +/// +/// `S` - application state type +/// +/// ## Example +/// +/// ```rust +/// # extern crate bytes; +/// # extern crate actix_web; +/// # extern crate futures; +/// # use actix_web::*; +/// #[macro_use] extern crate serde_derive; +/// use actix_web::State; +/// +/// /// Application state +/// struct App {msg: &'static str} +/// +/// #[derive(Deserialize)] +/// struct Info { +/// username: String, +/// } +/// +/// /// extract path info using serde +/// fn index(state: State, info: Path) -> Result { +/// Ok(format!("{} {}!", state.msg, info.username)) +/// } +/// +/// fn main() { +/// let app = Application::with_state(App{msg: "Welcome"}).resource( +/// "/{username}/index.html", // <- define path parameters +/// |r| r.method(Method::GET).with2(index)); // <- use `with` extractor +/// } +/// ``` +pub struct State (HttpRequest); + +impl Deref for State { + type Target = S; + + fn deref(&self) -> &S { + self.0.state() + } +} + +impl FromRequest for State +{ + type Result = FutureResult; + + #[inline] + fn from_request(req: &HttpRequest) -> Self::Result { + ok(State(req.clone())) + } +} diff --git a/src/lib.rs b/src/lib.rs index 4a29b1dc7..5ad8ff6ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,7 +141,7 @@ pub use application::Application; pub use httpmessage::HttpMessage; pub use httprequest::HttpRequest; pub use httpresponse::HttpResponse; -pub use handler::{Either, Responder, AsyncResponder, FutureResponse}; +pub use handler::{Either, Responder, AsyncResponder, FutureResponse, State}; pub use context::HttpContext; pub use server::HttpServer;