diff --git a/src/extractor.rs b/src/extractor.rs index d6559196b..eb4a2c84e 100644 --- a/src/extractor.rs +++ b/src/extractor.rs @@ -15,6 +15,16 @@ pub trait HttpRequestExtractor: Sized where S: 'static 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 diff --git a/src/json.rs b/src/json.rs index 18ec2be68..deb64c3bd 100644 --- a/src/json.rs +++ b/src/json.rs @@ -255,8 +255,8 @@ mod tests { let mut handler = with(|data: Json| data); let req = HttpRequest::default(); - let mut json = handler.handle(req).into_future(); - assert!(json.poll().is_err()); + let err = handler.handle(req).as_response().unwrap().error().is_some(); + assert!(err); let mut req = HttpRequest::default(); req.headers_mut().insert(header::CONTENT_TYPE, @@ -264,7 +264,7 @@ mod tests { req.headers_mut().insert(header::CONTENT_LENGTH, header::HeaderValue::from_static("16")); req.payload_mut().unread_data(Bytes::from_static(b"{\"name\": \"test\"}")); - let mut json = handler.handle(req).into_future(); - assert!(json.poll().is_ok()) + let ok = handler.handle(req).as_response().unwrap().error().is_none(); + assert!(ok) } } diff --git a/src/with.rs b/src/with.rs index f0a139c5c..cf93fe017 100644 --- a/src/with.rs +++ b/src/with.rs @@ -45,7 +45,7 @@ fn with(h: H) -> With } pub struct With - where H: WithHandler, + where H: WithHandler + 'static, T: HttpRequestExtractor, S: 'static, { @@ -62,15 +62,33 @@ impl Handler for With type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { - let fut = Box::new(T::extract(&req)); - - Reply::async( - WithHandlerFut{ - req, - hnd: Rc::clone(&self.hnd), - fut1: Some(fut), - fut2: None, - }) + let mut fut = T::extract(&req); + match fut.poll() { + Ok(Async::Ready(item)) => { + let hnd: &mut H = unsafe{&mut *self.hnd.get()}; + match hnd.handle(item).respond_to(req.without_state()) { + Ok(item) => match item.into().into() { + ReplyItem::Message(resp) => Reply::response(resp), + ReplyItem::Future(fut) => Reply::async( + WithHandlerFut{ + req, + hnd: Rc::clone(&self.hnd), + fut1: None, + fut2: Some(fut), + }) + }, + Err(e) => Reply::response(e.into()), + } + } + Ok(Async::NotReady) => Reply::async( + WithHandlerFut{ + req, + hnd: Rc::clone(&self.hnd), + fut1: Some(Box::new(fut)), + fut2: None, + }), + Err(e) => Reply::response(e), + } } } @@ -154,17 +172,52 @@ impl Handler for With2 type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { - let fut = Box::new(T1::extract(&req)); - - Reply::async( - WithHandlerFut2{ - req, - hnd: Rc::clone(&self.hnd), - item: None, - fut1: Some(fut), - fut2: None, - fut3: None, - }) + let mut fut = T1::extract(&req); + match fut.poll() { + Ok(Async::Ready(item1)) => { + let mut fut = T2::extract(&req); + match fut.poll() { + Ok(Async::Ready(item2)) => { + let hnd: &mut F = unsafe{&mut *self.hnd.get()}; + match (*hnd)(item1, item2).respond_to(req.without_state()) { + Ok(item) => match item.into().into() { + ReplyItem::Message(resp) => Reply::response(resp), + ReplyItem::Future(fut) => Reply::async( + WithHandlerFut2{ + req, + item: None, + hnd: Rc::clone(&self.hnd), + fut1: None, + fut2: None, + fut3: Some(fut), + }) + }, + Err(e) => Reply::response(e.into()), + } + }, + Ok(Async::NotReady) => Reply::async( + WithHandlerFut2{ + req, + hnd: Rc::clone(&self.hnd), + item: Some(item1), + fut1: None, + fut2: Some(Box::new(fut)), + fut3: None, + }), + Err(e) => Reply::response(e), + } + }, + Ok(Async::NotReady) => Reply::async( + WithHandlerFut2{ + req, + hnd: Rc::clone(&self.hnd), + item: None, + fut1: Some(Box::new(fut)), + fut2: None, + fut3: None, + }), + Err(e) => Reply::response(e), + } } } diff --git a/tests/test_handlers.rs b/tests/test_handlers.rs index d7a8bc45d..909c9ddf9 100644 --- a/tests/test_handlers.rs +++ b/tests/test_handlers.rs @@ -62,6 +62,60 @@ fn test_query_extractor() { assert_eq!(response.status(), StatusCode::BAD_REQUEST); } +#[test] +fn test_path_and_query_extractor() { + let mut srv = test::TestServer::new(|app| { + app.resource( + "/{username}/index.html", |r| r.route().with2( + |p: Path, q: Query| + format!("Welcome {} - {}!", p.username, q.username))); + } + ); + + // client request + let request = srv.get().uri(srv.url("/test1/index.html?username=test2")) + .finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = srv.execute(response.body()).unwrap(); + assert_eq!(bytes, Bytes::from_static(b"Welcome test1 - test2!")); + + // client request + let request = srv.get().uri(srv.url("/test1/index.html")) + .finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert_eq!(response.status(), StatusCode::BAD_REQUEST); +} + +#[test] +fn test_path_and_query_extractor2() { + let mut srv = test::TestServer::new(|app| { + app.resource( + "/{username}/index.html", |r| r.route().with3( + |_: HttpRequest, p: Path, q: Query| + format!("Welcome {} - {}!", p.username, q.username))); + } + ); + + // client request + let request = srv.get().uri(srv.url("/test1/index.html?username=test2")) + .finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = srv.execute(response.body()).unwrap(); + assert_eq!(bytes, Bytes::from_static(b"Welcome test1 - test2!")); + + // client request + let request = srv.get().uri(srv.url("/test1/index.html")) + .finish().unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert_eq!(response.status(), StatusCode::BAD_REQUEST); +} + #[test] fn test_non_ascii_route() { let mut srv = test::TestServer::new(|app| {