diff --git a/src/application.rs b/src/application.rs index e890787cb..91514d151 100644 --- a/src/application.rs +++ b/src/application.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use futures::Future; use error::Error; -use route::{RouteHandler, Reply, Handler, WrapHandler, AsyncHandler}; +use route::{RouteHandler, Reply, Handler, FromRequest, WrapHandler, AsyncHandler}; use resource::Resource; use recognizer::{RouteRecognizer, check_pattern}; use httprequest::HttpRequest; @@ -190,7 +190,7 @@ impl ApplicationBuilder where S: 'static { pub fn handler(&mut self, path: P, handler: F) -> &mut Self where P: Into, F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static + R: FromRequest + 'static { self.parts.as_mut().expect("Use after finish") .handlers.insert(path.into(), Box::new(WrapHandler::new(handler))); diff --git a/src/dev.rs b/src/dev.rs index 11484107f..537590651 100644 --- a/src/dev.rs +++ b/src/dev.rs @@ -10,7 +10,7 @@ // dev specific pub use pipeline::Pipeline; -pub use route::Handler; +pub use route::{Handler, FromRequest}; pub use channel::{HttpChannel, HttpHandler}; pub use recognizer::{FromParam, RouteRecognizer}; diff --git a/src/httpcodes.rs b/src/httpcodes.rs index 44415f5f3..013e16d39 100644 --- a/src/httpcodes.rs +++ b/src/httpcodes.rs @@ -3,8 +3,7 @@ use http::StatusCode; use body::Body; -use route::Reply; -use route::RouteHandler; +use route::{Reply, RouteHandler, FromRequest}; use httprequest::HttpRequest; use httpresponse::{HttpResponse, HttpResponseBuilder}; @@ -74,6 +73,12 @@ impl RouteHandler for StaticResponse { } } +impl FromRequest for StaticResponse { + fn from_request(self, _: HttpRequest) -> Reply { + Reply::response(HttpResponse::new(self.0, Body::Empty)) + } +} + impl From for HttpResponse { fn from(st: StaticResponse) -> Self { st.response() diff --git a/src/httprequest.rs b/src/httprequest.rs index 393330153..debfefe3b 100644 --- a/src/httprequest.rs +++ b/src/httprequest.rs @@ -83,6 +83,11 @@ impl HttpRequest<()> { impl HttpRequest { + /// Construct new http request without state. + pub fn clone_without_state(&self) -> HttpRequest { + HttpRequest(Rc::clone(&self.0), Rc::new(())) + } + /// get mutable reference for inner message fn as_mut(&mut self) -> &mut HttpMessage { let r: &HttpMessage = self.0.as_ref(); diff --git a/src/resource.rs b/src/resource.rs index 6e82b60ae..b13fda249 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -5,7 +5,7 @@ use http::Method; use futures::Future; use error::Error; -use route::{Reply, Handler, RouteHandler, AsyncHandler, WrapHandler}; +use route::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler}; use httprequest::HttpRequest; use httpresponse::HttpResponse; use httpcodes::{HTTPNotFound, HTTPMethodNotAllowed}; @@ -53,14 +53,14 @@ impl Resource where S: 'static { } /// Set resource name - pub fn set_name>(&mut self, name: T) { + pub fn name>(&mut self, name: T) { self.name = name.into(); } /// Register handler for specified method. pub fn handler(&mut self, method: Method, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static, + R: FromRequest + 'static, { self.routes.insert(method, Box::new(WrapHandler::new(handler))); } @@ -83,28 +83,28 @@ impl Resource where S: 'static { /// Register handler for `GET` method. pub fn get(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static, { + R: FromRequest + 'static, { self.routes.insert(Method::GET, Box::new(WrapHandler::new(handler))); } /// Register handler for `POST` method. pub fn post(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static, { + R: FromRequest + 'static, { self.routes.insert(Method::POST, Box::new(WrapHandler::new(handler))); } /// Register handler for `PUT` method. pub fn put(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static, { + R: FromRequest + 'static, { self.routes.insert(Method::PUT, Box::new(WrapHandler::new(handler))); } /// Register handler for `DELETE` method. pub fn delete(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static, { + R: FromRequest + 'static, { self.routes.insert(Method::DELETE, Box::new(WrapHandler::new(handler))); } } diff --git a/src/route.rs b/src/route.rs index 1550751c2..1ab32a56f 100644 --- a/src/route.rs +++ b/src/route.rs @@ -14,16 +14,20 @@ use httpresponse::HttpResponse; pub trait Handler: 'static { /// The type of value that handler will return. - type Result: Into; + type Result: FromRequest; /// Handle request fn handle(&self, req: HttpRequest) -> Self::Result; } +pub trait FromRequest { + fn from_request(self, req: HttpRequest) -> Reply; +} + /// Handler for Fn() impl Handler for F where F: Fn(HttpRequest) -> R + 'static, - R: Into + 'static + R: FromRequest + 'static { type Result = R; @@ -67,28 +71,41 @@ impl Reply { } } -#[cfg(not(actix_nightly))] -impl> From for Reply -{ - fn from(item: T) -> Self { - Reply(ReplyItem::Message(item.into())) +impl FromRequest for Reply { + fn from_request(self, _: HttpRequest) -> Reply { + self + } +} + +impl FromRequest for HttpResponse { + fn from_request(self, _: HttpRequest) -> Reply { + Reply(ReplyItem::Message(self)) } } #[cfg(actix_nightly)] -default impl> From for Reply +default impl FromRequest for T { - fn from(item: T) -> Self { - Reply(ReplyItem::Message(item.into())) + fn from_request(self, req: HttpRequest) -> Reply { + self.from_request(req) } } #[cfg(actix_nightly)] -default impl, E: Into> From> for Reply { - fn from(res: StdResult) -> Self { - match res { - Ok(val) => val.into().into(), - Err(err) => err.into().into(), +default impl> FromRequest for StdResult { + fn from_request(self, req: HttpRequest) -> Reply { + match self { + Ok(val) => val.from_request(req), + Err(err) => Reply(ReplyItem::Message(err.into().into())), + } + } +} + +impl> FromRequest for StdResult { + fn from_request(self, _: HttpRequest) -> Reply { + match self { + Ok(val) => val, + Err(err) => Reply(ReplyItem::Message(err.into().into())), } } } @@ -97,22 +114,37 @@ impl> From> for Reply { fn from(res: StdResult) -> Self { match res { Ok(val) => val, - Err(err) => err.into().into(), + Err(err) => Reply(ReplyItem::Message(err.into().into())), } } } -impl>, S: 'static> From> for Reply -{ - fn from(item: HttpContext) -> Self { - Reply(ReplyItem::Actor(Box::new(item))) +impl> FromRequest for StdResult { + fn from_request(self, _: HttpRequest) -> Reply { + match self { + Ok(val) => Reply(ReplyItem::Message(val)), + Err(err) => Reply(ReplyItem::Message(err.into().into())), + } } } -impl From>> for Reply +impl>, S: 'static> FromRequest for HttpContext { - fn from(item: Box>) -> Self { - Reply(ReplyItem::Future(item)) + fn from_request(self, _: HttpRequest) -> Reply { + Reply(ReplyItem::Actor(Box::new(self))) + } +} + +impl>, S: 'static> From> for Reply { + fn from(ctx: HttpContext) -> Reply { + Reply(ReplyItem::Actor(Box::new(ctx))) + } +} + +impl FromRequest for Box> +{ + fn from_request(self, _: HttpRequest) -> Reply { + Reply(ReplyItem::Future(self)) } } @@ -125,7 +157,7 @@ pub(crate) trait RouteHandler: 'static { pub(crate) struct WrapHandler where H: Handler, - R: Into, + R: FromRequest, S: 'static, { h: H, @@ -134,7 +166,7 @@ struct WrapHandler impl WrapHandler where H: Handler, - R: Into, + R: FromRequest, S: 'static, { pub fn new(h: H) -> Self { @@ -144,11 +176,12 @@ impl WrapHandler impl RouteHandler for WrapHandler where H: Handler, - R: Into + 'static, + R: FromRequest + 'static, S: 'static, { fn handle(&self, req: HttpRequest) -> Reply { - self.h.handle(req).into() + let req2 = req.clone_without_state(); + self.h.handle(req).from_request(req2) } }