diff --git a/.travis.yml b/.travis.yml index 195f539c4..72e0dbb38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ after_success: - | if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh) - cargo tarpaulin --exclude examples --out Xml + cargo tarpaulin --exclude ./examples/* --out Xml bash <(curl -s https://codecov.io/bash) echo "Uploaded code coverage" fi diff --git a/examples/basic.rs b/examples/basic.rs index 3e753895b..cf9c78aa3 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -71,7 +71,7 @@ fn main() { // with path parameters .resource("/user/{name}/", |r| r.route().method(Method::GET).f(with_param)) // async handler - .resource("/async/{name}", |r| r.route().method(Method::GET).async(index_async)) + .resource("/async/{name}", |r| r.route().method(Method::GET).a(index_async)) // redirect .resource("/", |r| r.route().method(Method::GET).f(|req| { println!("{:?}", req); diff --git a/guide/src/qs_4.md b/guide/src/qs_4.md index cc62a0118..c8683591d 100644 --- a/guide/src/qs_4.md +++ b/guide/src/qs_4.md @@ -96,31 +96,50 @@ There are two different types of async handlers. Response object could be generated asynchronously. In this case handle must return `Future` object that resolves to `HttpResponse`, i.e: -```rust,ignore -fn index(req: HttpRequest) -> Box> { - ... -} -``` +```rust +# extern crate actix_web; +# extern crate futures; +# extern crate bytes; +# use actix_web::*; +# use bytes::Bytes; +# use futures::stream::once; +# use futures::future::{FutureResult, result}; +fn index(req: HttpRequest) -> FutureResult { -This handler can be registered with `ApplicationBuilder::async()` and -`Resource::async()` methods. - -Or response body can be generated asynchronously. In this case body -must implement stream trait `Stream`, i.e: - - -```rust,ignore -fn index(req: HttpRequest) -> HttpResponse { - let body: Box> = Box::new(SomeStream::new()); - - HttpResponse::Ok(). - .content_type("application/json") - .body(Body::Streaming(body)).unwrap() + result(HttpResponse::Ok() + .content_type("text/html") + .body(format!("Hello!")) + .map_err(|e| e.into())) } fn main() { Application::default("/") - .async("/async", index) + .route("/async", |r| r.a(index)) + .finish(); +} +``` + +Or response body can be generated asynchronously. In this case body +must implement stream trait `Stream`, i.e: + +```rust +# extern crate actix_web; +# extern crate futures; +# extern crate bytes; +# use actix_web::*; +# use bytes::Bytes; +# use futures::stream::once; +fn index(req: HttpRequest) -> HttpResponse { + let body = once(Ok(Bytes::from_static(b"test"))); + + HttpResponse::Ok() + .content_type("application/json") + .body(Body::Streaming(Box::new(body))).unwrap() +} + +fn main() { + Application::default("/") + .route("/async", |r| r.f(index)) .finish(); } ``` diff --git a/src/application.rs b/src/application.rs index 20de925c3..822a7c472 100644 --- a/src/application.rs +++ b/src/application.rs @@ -2,7 +2,8 @@ use std::rc::Rc; use std::collections::HashMap; use handler::{Reply, RouteHandler}; -use resource::{Route, Resource}; +use route::Route; +use resource::Resource; use recognizer::{RouteRecognizer, check_pattern}; use httprequest::HttpRequest; use channel::HttpHandler; diff --git a/src/lib.rs b/src/lib.rs index 070514add..d365c87c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,7 @@ mod encoding; mod httprequest; mod httpresponse; mod payload; +mod route; mod resource; mod recognizer; mod handler; @@ -84,7 +85,8 @@ pub use httprequest::{HttpRequest, UrlEncoded}; pub use httpresponse::HttpResponse; pub use payload::{Payload, PayloadItem}; pub use handler::{Reply, Json, FromRequest}; -pub use resource::{Route, Resource}; +pub use route::Route; +pub use resource::Resource; pub use recognizer::Params; pub use server::HttpServer; pub use context::HttpContext; diff --git a/src/resource.rs b/src/resource.rs index a7b41d564..989d78f80 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,96 +1,13 @@ use std::marker::PhantomData; use http::Method; -use futures::Future; -use error::Error; -use pred::{self, Predicate}; -use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler}; +use route::Route; +use handler::{Reply, Handler, RouteHandler, WrapHandler}; use httpcodes::HTTPNotFound; use httprequest::HttpRequest; -use httpresponse::HttpResponse; -/// Resource route definition -/// -/// Route uses builder-like pattern for configuration. -/// If handler is not explicitly set, default *404 Not Found* handler is used. -pub struct Route { - preds: Vec>>, - handler: Box>, -} - -impl Default for Route { - - fn default() -> Route { - Route { - preds: Vec::new(), - handler: Box::new(WrapHandler::new(|_| HTTPNotFound)), - } - } -} - -impl Route { - - pub(crate) fn check(&self, req: &mut HttpRequest) -> bool { - for pred in &self.preds { - if !pred.check(req) { - return false - } - } - true - } - - pub(crate) fn handle(&self, req: HttpRequest) -> Reply { - self.handler.handle(req) - } - - /// Add match predicate to route. - pub fn p(&mut self, p: Box>) -> &mut Self { - self.preds.push(p); - self - } - - /// Add predicates to route. - pub fn predicates

(&mut self, preds: P) -> &mut Self - where P: IntoIterator>> - { - self.preds.extend(preds.into_iter()); - self - } - - /// Add method check to route. This method could be called multiple times. - pub fn method(&mut self, method: Method) -> &mut Self { - self.preds.push(pred::Method(method)); - self - } - - /// Set handler object. Usually call to this method is last call - /// during route configuration, because it does not return reference to self. - pub fn h>(&mut self, handler: H) { - self.handler = Box::new(WrapHandler::new(handler)); - } - - /// Set handler function. Usually call to this method is last call - /// during route configuration, because it does not return reference to self. - pub fn f(&mut self, handler: F) - where F: Fn(HttpRequest) -> R + 'static, - R: FromRequest + 'static, - { - self.handler = Box::new(WrapHandler::new(handler)); - } - - /// Set handler function. - pub fn async(&mut self, handler: F) - where F: Fn(HttpRequest) -> R + 'static, - R: Future + 'static, - { - self.handler = Box::new(AsyncHandler::new(handler)); - } -} - -/// Http resource -/// -/// `Resource` is an entry in route table which corresponds to requested URL. +/// *Resource* is an entry in route table which corresponds to requested URL. /// /// Resource in turn has at least one route. /// Route consists of an object that implements `Handler` trait (handler) diff --git a/src/route.rs b/src/route.rs new file mode 100644 index 000000000..7739ff71b --- /dev/null +++ b/src/route.rs @@ -0,0 +1,88 @@ +use http::Method; +use futures::Future; + +use error::Error; +use pred::{self, Predicate}; +use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler}; +use httpcodes::HTTPNotFound; +use httprequest::HttpRequest; +use httpresponse::HttpResponse; + + +/// Resource route definition +/// +/// Route uses builder-like pattern for configuration. +/// If handler is not explicitly set, default *404 Not Found* handler is used. +pub struct Route { + preds: Vec>>, + handler: Box>, +} + +impl Default for Route { + + fn default() -> Route { + Route { + preds: Vec::new(), + handler: Box::new(WrapHandler::new(|_| HTTPNotFound)), + } + } +} + +impl Route { + + pub(crate) fn check(&self, req: &mut HttpRequest) -> bool { + for pred in &self.preds { + if !pred.check(req) { + return false + } + } + true + } + + pub(crate) fn handle(&self, req: HttpRequest) -> Reply { + self.handler.handle(req) + } + + /// Add match predicate to route. + pub fn p(&mut self, p: Box>) -> &mut Self { + self.preds.push(p); + self + } + + /// Add predicates to route. + pub fn predicates

(&mut self, preds: P) -> &mut Self + where P: IntoIterator>> + { + self.preds.extend(preds.into_iter()); + self + } + + /// Add method check to route. This method could be called multiple times. + pub fn method(&mut self, method: Method) -> &mut Self { + self.preds.push(pred::Method(method)); + self + } + + /// Set handler object. Usually call to this method is last call + /// during route configuration, because it does not return reference to self. + pub fn h>(&mut self, handler: H) { + self.handler = Box::new(WrapHandler::new(handler)); + } + + /// Set handler function. Usually call to this method is last call + /// during route configuration, because it does not return reference to self. + pub fn f(&mut self, handler: F) + where F: Fn(HttpRequest) -> R + 'static, + R: FromRequest + 'static, + { + self.handler = Box::new(WrapHandler::new(handler)); + } + + /// Set async handler function. + pub fn a(&mut self, handler: F) + where F: Fn(HttpRequest) -> R + 'static, + R: Future + 'static, + { + self.handler = Box::new(AsyncHandler::new(handler)); + } +}