diff --git a/README.md b/README.md index 695e67675..53defdd26 100644 --- a/README.md +++ b/README.md @@ -108,8 +108,8 @@ fn main() { HttpServer::new( Application::default("/") .middleware(middlewares::Logger::default()) // <- register logger middleware - .resource("/ws/", |r| r.method(Method::GET) - .handler(|req| ws::start(req, MyWebSocket))) // <- websocket route + .resource("/ws/", |r| + r.method(Method::GET).f(|req| ws::start(req, MyWebSocket))) // <- websocket route .route("/", fs::StaticFiles::new("examples/static/", true))) // <- serve static files .serve::<_, ()>("127.0.0.1:8080").unwrap(); diff --git a/examples/basic.rs b/examples/basic.rs index a7e375110..3db4a1f38 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -69,11 +69,11 @@ fn main() { // register simple handle r, handle all methods .handler("/index.html", index) // with path parameters - .resource("/user/{name}/", |r| r.route().method(Method::GET).handler(with_param)) + .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)) // redirect - .resource("/", |r| r.route().method(Method::GET).handler(|req| { + .resource("/", |r| r.route().method(Method::GET).f(|req| { println!("{:?}", req); httpcodes::HTTPFound diff --git a/examples/state.rs b/examples/state.rs index afdc5e78f..db0347945 100644 --- a/examples/state.rs +++ b/examples/state.rs @@ -65,8 +65,9 @@ fn main() { .middleware(middlewares::Logger::default()) // websocket route .resource( - "/ws/", |r| r.route().method(Method::GET) - .handler(|req| ws::start(req, MyWebSocket{counter: 0}))) + "/ws/", |r| r.route() + .method(Method::GET) + .f(|req| ws::start(req, MyWebSocket{counter: 0}))) // register simple handler, handle all methods .handler("/", index)) .serve::<_, ()>("127.0.0.1:8080").unwrap(); diff --git a/examples/websocket.rs b/examples/websocket.rs index 0772b3c99..f6ead4220 100644 --- a/examples/websocket.rs +++ b/examples/websocket.rs @@ -65,7 +65,7 @@ fn main() { // enable logger .middleware(middlewares::Logger::default()) // websocket route - .resource("/ws/", |r| r.route().method(Method::GET).handler(ws_index)) + .resource("/ws/", |r| r.route().method(Method::GET).f(ws_index)) // static files .route("/", fs::StaticFiles::new("examples/static/", true))) // start http server on 127.0.0.1:8080 diff --git a/guide/src/qs_10.md b/guide/src/qs_10.md index 66a049d22..23275cb4f 100644 --- a/guide/src/qs_10.md +++ b/guide/src/qs_10.md @@ -77,8 +77,8 @@ fn main() { .header("X-Version", "0.2") .finish()) .resource("/test", |r| { - r.method(Method::GET).handler(|req| httpcodes::HTTPOk); - r.method(Method::HEAD).handler(|req| httpcodes::HTTPMethodNotAllowed); + r.method(Method::GET).f(|req| httpcodes::HTTPOk); + r.method(Method::HEAD).f(|req| httpcodes::HTTPMethodNotAllowed); }) .finish(); } diff --git a/guide/src/qs_12.md b/guide/src/qs_12.md index a280e0759..b85caacfb 100644 --- a/guide/src/qs_12.md +++ b/guide/src/qs_12.md @@ -2,7 +2,8 @@ ## Individual file -It is possible to serve static files with tail path pattern and `NamedFile`. +It is possible to serve static files with custom path pattern and `NamedFile`. To +match path tail we can use `.*` regex. ```rust extern crate actix_web; @@ -16,7 +17,7 @@ fn index(req: HttpRequest) -> Result { fn main() { Application::default("/") - .resource(r"/a/{tail:*}", |r| r.method(Method::GET).handler(index)) + .resource(r"/a/{tail:.*}", |r| r.method(Method::GET).f(index)) .finish(); } ``` diff --git a/guide/src/qs_2.md b/guide/src/qs_2.md index 480aacb86..b8179db35 100644 --- a/guide/src/qs_2.md +++ b/guide/src/qs_2.md @@ -49,7 +49,7 @@ request handler with the application's `resource` on a particular *HTTP method* # } # fn main() { let app = Application::default("/") - .resource("/", |r| r.method(Method::GET).handler(index)) + .resource("/", |r| r.method(Method::GET).f(index)) .finish(); # } ``` @@ -80,7 +80,7 @@ fn main() { HttpServer::new( Application::default("/") - .resource("/", |r| r.route().handler(index))) + .resource("/", |r| r.route().f(index))) .serve::<_, ()>("127.0.0.1:8088").unwrap(); println!("Started http server: 127.0.0.1:8088"); diff --git a/guide/src/qs_3.md b/guide/src/qs_3.md index 84367a993..f94e27266 100644 --- a/guide/src/qs_3.md +++ b/guide/src/qs_3.md @@ -21,7 +21,7 @@ has same url path prefix: # } # fn main() { let app = Application::default("/prefix") - .resource("/index.html", |r| r.method(Method::GET).handler(index)) + .resource("/index.html", |r| r.method(Method::GET).f(index)) .finish() # } ``` @@ -41,13 +41,13 @@ use tokio_core::net::TcpStream; fn main() { HttpServer::::new(vec![ Application::default("/app1") - .resource("/", |r| r.route().handler(|r| httpcodes::HTTPOk)) + .resource("/", |r| r.route().f(|r| httpcodes::HTTPOk)) .finish(), Application::default("/app2") - .resource("/", |r| r.route().handler(|r| httpcodes::HTTPOk)) + .resource("/", |r| r.route().f(|r| httpcodes::HTTPOk)) .finish(), Application::default("/") - .resource("/", |r| r.route().handler(|r| httpcodes::HTTPOk)) + .resource("/", |r| r.route().f(|r| httpcodes::HTTPOk)) .finish(), ]); } diff --git a/guide/src/qs_4.md b/guide/src/qs_4.md index 0e0ff981c..cc62a0118 100644 --- a/guide/src/qs_4.md +++ b/guide/src/qs_4.md @@ -79,7 +79,7 @@ fn main() { HttpServer::new( Application::default("/") .resource("/", |r| r.method( - Method::GET).handler(|req| {MyObj{name: "user".to_owned()}}))) + Method::GET).f(|req| {MyObj{name: "user".to_owned()}}))) .serve::<_, ()>("127.0.0.1:8088").unwrap(); println!("Started http server: 127.0.0.1:8088"); diff --git a/guide/src/qs_5.md b/guide/src/qs_5.md index 4ccceceaf..9e024926f 100644 --- a/guide/src/qs_5.md +++ b/guide/src/qs_5.md @@ -55,8 +55,8 @@ if no route could be matched default response `HTTPMethodNotAllowed` get resturn fn main() { Application::default("/") .resource("/prefix", |r| { - r.method(Method::GET).handler(|r| httpcodes::HTTPOk); - r.method(Method::POST).handler(|r| httpcodes::HTTPForbidden); + r.method(Method::GET).h(httpcodes::HTTPOk); + r.method(Method::POST).h(httpcodes::HTTPForbidden); }) .finish(); } @@ -87,7 +87,7 @@ fn index(req: HttpRequest) -> String { fn main() { Application::default("/") - .resource("/{name}", |r| r.method(Method::GET).handler(index)) + .resource("/{name}", |r| r.method(Method::GET).f(index)) .finish(); } ``` @@ -105,7 +105,7 @@ You can also specify a custom regex in the form `{identifier:regex}`: fn main() { Application::default("/") - .resource(r"{name:\d+}", |r| r.method(Method::GET).handler(index)) + .resource(r"{name:\d+}", |r| r.method(Method::GET).f(index)) .finish(); } ``` @@ -126,7 +126,7 @@ fn index(req: HttpRequest) -> Result { fn main() { Application::default("/") - .resource(r"/a/{v1}/{v2}/", |r| r.route().handler(index)) + .resource(r"/a/{v1}/{v2}/", |r| r.route().f(index)) .finish(); } ``` @@ -138,7 +138,7 @@ It is possible to match path tail with custom `.*` regex. ```rust,ignore fn main() { Application::default("/") - .resource(r"/test/{tail:.*}", |r| r.method(Method::GET).handler(index)) + .resource(r"/test/{tail:.*}", |r| r.method(Method::GET).f(index)) .finish(); } ``` @@ -174,7 +174,7 @@ fn index(req: HttpRequest) -> Result { fn main() { Application::default("/") - .resource(r"/a/{tail:.*}", |r| r.method(Method::GET).handler(index)) + .resource(r"/a/{tail:.*}", |r| r.method(Method::GET).f(index)) .finish(); } ``` diff --git a/guide/src/qs_6.md b/guide/src/qs_6.md index 096459b78..5e4e220b8 100644 --- a/guide/src/qs_6.md +++ b/guide/src/qs_6.md @@ -30,7 +30,7 @@ fn index(req: HttpRequest) -> String { fn main() { Application::build("/", AppState{counter: Cell::new(0)}) - .resource("/", |r| r.method(Method::GET).handler(index)) + .resource("/", |r| r.method(Method::GET).f(index)) .finish(); } ``` diff --git a/guide/src/qs_7.md b/guide/src/qs_7.md index fcf2dec83..8cadb61e7 100644 --- a/guide/src/qs_7.md +++ b/guide/src/qs_7.md @@ -54,7 +54,7 @@ fn index(req: HttpRequest) -> Result> { fn main() { Application::default("/") - .resource(r"/a/{name}", |r| r.method(Method::GET).handler(index)) + .resource(r"/a/{name}", |r| r.method(Method::GET).f(index)) .finish(); } ``` diff --git a/src/application.rs b/src/application.rs index 3e05487e0..8d8bf3d02 100644 --- a/src/application.rs +++ b/src/application.rs @@ -134,8 +134,8 @@ impl ApplicationBuilder where S: 'static { /// fn main() { /// let app = Application::default("/") /// .resource("/test", |r| { - /// r.method(Method::GET).handler(|_| httpcodes::HTTPOk); - /// r.method(Method::HEAD).handler(|_| httpcodes::HTTPMethodNotAllowed); + /// r.method(Method::GET).f(|_| httpcodes::HTTPOk); + /// r.method(Method::HEAD).f(|_| httpcodes::HTTPMethodNotAllowed); /// }) /// .finish(); /// } diff --git a/src/httpcodes.rs b/src/httpcodes.rs index 64d308d5f..5aa43b059 100644 --- a/src/httpcodes.rs +++ b/src/httpcodes.rs @@ -3,7 +3,7 @@ use http::{StatusCode, Error as HttpError}; use body::Body; -use route::{Reply, RouteHandler, FromRequest}; +use route::{Reply, Handler, RouteHandler, FromRequest}; use httprequest::HttpRequest; use httpresponse::{HttpResponse, HttpResponseBuilder}; @@ -67,6 +67,14 @@ impl StaticResponse { } } +impl Handler for StaticResponse { + type Result = HttpResponse; + + fn handle(&self, _: HttpRequest) -> HttpResponse { + HttpResponse::new(self.0, Body::Empty) + } +} + impl RouteHandler for StaticResponse { fn handle(&self, _: HttpRequest) -> Reply { Reply::response(HttpResponse::new(self.0, Body::Empty)) diff --git a/src/middlewares/defaultheaders.rs b/src/middlewares/defaultheaders.rs index cf2503e30..08d6a923f 100644 --- a/src/middlewares/defaultheaders.rs +++ b/src/middlewares/defaultheaders.rs @@ -21,8 +21,8 @@ use middlewares::{Response, Middleware}; /// .header("X-Version", "0.2") /// .finish()) /// .resource("/test", |r| { -/// r.method(Method::GET).handler(|_| httpcodes::HTTPOk); -/// r.method(Method::HEAD).handler(|_| httpcodes::HTTPMethodNotAllowed); +/// r.method(Method::GET).f(|_| httpcodes::HTTPOk); +/// r.method(Method::HEAD).f(|_| httpcodes::HTTPMethodNotAllowed); /// }) /// .finish(); /// } diff --git a/src/resource.rs b/src/resource.rs index c175b683f..fd669210a 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -10,7 +10,10 @@ use httpcodes::HTTPNotFound; use httprequest::HttpRequest; use httpresponse::HttpResponse; -/// Resource route definition. Route uses builder-like pattern for configuration. +/// 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>, @@ -55,16 +58,21 @@ impl Route { 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 handler(&mut self, handler: F) + pub fn f(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, R: FromRequest + 'static, { @@ -99,7 +107,7 @@ impl Route { /// fn main() { /// let app = Application::default("/") /// .resource( -/// "/", |r| r.route().method(Method::GET).handler(|r| HttpResponse::Ok())) +/// "/", |r| r.route().method(Method::GET).f(|r| HttpResponse::Ok())) /// .finish(); /// } pub struct Resource { @@ -147,7 +155,7 @@ impl Resource where S: 'static { /// "/", |r| r.route() /// .p(pred::Any(vec![pred::Get(), pred::Put()])) /// .p(pred::Header("Content-Type", "text/plain")) - /// .handler(|r| HttpResponse::Ok())) + /// .f(|r| HttpResponse::Ok())) /// .finish(); /// } pub fn route(&mut self) -> &mut Route { diff --git a/src/route.rs b/src/route.rs index 25223924a..91d70bced 100644 --- a/src/route.rs +++ b/src/route.rs @@ -227,6 +227,27 @@ impl RouteHandler for AsyncHandler } +/// Json response helper +/// +/// The `Json` type allows you to respond with well-formed JSON data: simply return a value of +/// type Json where T is the type of a structure to serialize into *JSON*. The +/// type `T` must implement the `Serialize` trait from *serde*. +/// +/// ```rust +/// # extern crate actix_web; +/// # #[macro_use] extern crate serde_derive; +/// # use actix_web::*; +/// # +/// #[derive(Serialize)] +/// struct MyObj { +/// name: String, +/// } +/// +/// fn index(req: HttpRequest) -> Result> { +/// Ok(Json(MyObj{name: req.match_info().query("name")?})) +/// } +/// # fn main() {} +/// ``` pub struct Json (pub T); impl FromRequest for Json { diff --git a/src/ws.rs b/src/ws.rs index e5e467e07..6c6f58221 100644 --- a/src/ws.rs +++ b/src/ws.rs @@ -43,7 +43,7 @@ //! //! fn main() { //! Application::default("/") -//! .resource("/ws/", |r| r.method(Method::GET).handler(ws_index)) // <- register websocket route +//! .resource("/ws/", |r| r.method(Method::GET).f(ws_index)) // <- register websocket route //! .finish(); //! } //! ``` diff --git a/tests/test_server.rs b/tests/test_server.rs index 5cd556c3b..45d0f46e4 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -16,7 +16,7 @@ fn create_server() -> HttpServer> { HttpServer::new( vec![Application::default("/") .resource("/", |r| - r.route().method(Method::GET).handler(|_| httpcodes::HTTPOk)) + r.route().method(Method::GET).h(httpcodes::HTTPOk)) .finish()]) } @@ -94,7 +94,7 @@ fn test_middlewares() { response: act_num2, finish: act_num3}) .resource("/", |r| - r.route().method(Method::GET).handler(|_| httpcodes::HTTPOk)) + r.route().method(Method::GET).h(httpcodes::HTTPOk)) .finish()]) .serve::<_, ()>("127.0.0.1:58904").unwrap(); sys.run();