From e332c1242fe233fe8dc8e5c336947d0ae24cfb5d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 4 Dec 2017 14:53:40 -0800 Subject: [PATCH] use Route for Applicaiton handlers --- README.md | 2 +- examples/basic.rs | 10 ++-- examples/state.rs | 2 +- examples/websocket.rs | 2 +- guide/src/qs_12.md | 2 +- guide/src/qs_5.md | 4 +- src/application.rs | 95 +++++++++++++++--------------------- src/dev.rs | 2 +- src/fs.rs | 4 +- src/{route.rs => handler.rs} | 0 src/httpcodes.rs | 2 +- src/httpresponse.rs | 2 +- src/lib.rs | 4 +- src/pipeline.rs | 2 +- src/resource.rs | 6 +-- src/ws.rs | 2 +- 16 files changed, 61 insertions(+), 80 deletions(-) rename src/{route.rs => handler.rs} (100%) diff --git a/README.md b/README.md index 53defdd2..98b3ea4c 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ fn main() { .middleware(middlewares::Logger::default()) // <- register logger middleware .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 + .route("/", |r| r.h(fs::StaticFiles::new("examples/static/", true)))) // <- serve static files .serve::<_, ()>("127.0.0.1:8080").unwrap(); Arbiter::system().send(msgs::SystemExit(0)); diff --git a/examples/basic.rs b/examples/basic.rs index 3db4a1f3..3e753895 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -66,8 +66,8 @@ fn main() { .secure(false) .finish() )) - // register simple handle r, handle all methods - .handler("/index.html", index) + // register simple route, handle all methods + .route("/index.html", |r| r.f(index)) // with path parameters .resource("/user/{name}/", |r| r.route().method(Method::GET).f(with_param)) // async handler @@ -81,15 +81,15 @@ fn main() { .header("LOCATION", "/index.html") .body(Body::Empty) })) - .handler("/test", |req| { + .route("/test", |r| r.f(|req| { match *req.method() { Method::GET => httpcodes::HTTPOk, Method::POST => httpcodes::HTTPMethodNotAllowed, _ => httpcodes::HTTPNotFound, } - }) + })) // static files - .route("/static", fs::StaticFiles::new("examples/static/", true))) + .route("/static", |r| r.h(fs::StaticFiles::new("examples/static/", true)))) .serve::<_, ()>("127.0.0.1:8080").unwrap(); println!("Started http server: 127.0.0.1:8080"); diff --git a/examples/state.rs b/examples/state.rs index db034794..f7e98041 100644 --- a/examples/state.rs +++ b/examples/state.rs @@ -69,7 +69,7 @@ fn main() { .method(Method::GET) .f(|req| ws::start(req, MyWebSocket{counter: 0}))) // register simple handler, handle all methods - .handler("/", index)) + .route("/", |r| r.f(index))) .serve::<_, ()>("127.0.0.1:8080").unwrap(); println!("Started http server: 127.0.0.1:8080"); diff --git a/examples/websocket.rs b/examples/websocket.rs index f6ead422..0187f0c0 100644 --- a/examples/websocket.rs +++ b/examples/websocket.rs @@ -67,7 +67,7 @@ fn main() { // websocket route .resource("/ws/", |r| r.route().method(Method::GET).f(ws_index)) // static files - .route("/", fs::StaticFiles::new("examples/static/", true))) + .route("/", |r| r.h(fs::StaticFiles::new("examples/static/", true)))) // start http server on 127.0.0.1:8080 .serve::<_, ()>("127.0.0.1:8080").unwrap(); diff --git a/guide/src/qs_12.md b/guide/src/qs_12.md index b85caacf..cc64a25e 100644 --- a/guide/src/qs_12.md +++ b/guide/src/qs_12.md @@ -32,7 +32,7 @@ extern crate actix_web; fn main() { actix_web::Application::default("/") - .route("/static", actix_web::fs::StaticFiles::new(".", true)) + .route("/static", |r| r.h(actix_web::fs::StaticFiles::new(".", true))) .finish(); } ``` diff --git a/guide/src/qs_5.md b/guide/src/qs_5.md index 9e024926..53573871 100644 --- a/guide/src/qs_5.md +++ b/guide/src/qs_5.md @@ -18,7 +18,7 @@ fn index(req: HttpRequest) -> HttpResponse { fn main() { Application::default("/") - .handler("/prefix", index) + .route("/prefix", |r| r.f(index)) .finish(); } ``` @@ -37,7 +37,7 @@ fn index(req: HttpRequest) -> HttpResponse { fn main() { Application::default("/app") - .handler("/prefix", index) + .route("/prefix", |r| r.f(index)) .finish(); } ``` diff --git a/src/application.rs b/src/application.rs index 8d8bf3d0..20de925c 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,13 +1,10 @@ use std::rc::Rc; use std::collections::HashMap; -use futures::Future; -use error::Error; -use route::{RouteHandler, Reply, Handler, FromRequest, WrapHandler, AsyncHandler}; -use resource::Resource; +use handler::{Reply, RouteHandler}; +use resource::{Route, Resource}; use recognizer::{RouteRecognizer, check_pattern}; use httprequest::HttpRequest; -use httpresponse::HttpResponse; use channel::HttpHandler; use pipeline::Pipeline; use middlewares::Middleware; @@ -18,7 +15,7 @@ pub struct Application { state: Rc, prefix: String, default: Resource, - handlers: HashMap>>, + routes: Vec<(String, Route)>, router: RouteRecognizer>, middlewares: Rc>>, } @@ -34,10 +31,10 @@ impl Application { } h.handle(req) } else { - for (prefix, handler) in &self.handlers { - if req.path().starts_with(prefix) { - req.set_prefix(prefix.len()); - return handler.handle(req) + for route in &self.routes { + if req.path().starts_with(&route.0) && route.1.check(&mut req) { + req.set_prefix(route.0.len()); + return route.1.handle(req) } } self.default.handle(req) @@ -66,7 +63,7 @@ impl Application<()> { state: (), prefix: prefix.into(), default: Resource::default_not_found(), - handlers: HashMap::new(), + routes: Vec::new(), resources: HashMap::new(), middlewares: Vec::new(), }) @@ -85,7 +82,7 @@ impl Application where S: 'static { state: state, prefix: prefix.into(), default: Resource::default_not_found(), - handlers: HashMap::new(), + routes: Vec::new(), resources: HashMap::new(), middlewares: Vec::new(), }) @@ -97,7 +94,7 @@ struct ApplicationBuilderParts { state: S, prefix: String, default: Resource, - handlers: HashMap>>, + routes: Vec<(String, Route)>, resources: HashMap>, middlewares: Vec>, } @@ -168,8 +165,10 @@ impl ApplicationBuilder where S: 'static { self } - /// This method register handler for specified path prefix. - /// Any path that starts with this prefix matches handler. + /// This method register route for specified path prefix. + /// Route maches based on path prefix, variable path patterns are not available + /// in this case. If you need variable path patterns consider using *resource()* + /// method. /// /// ```rust /// extern crate actix_web; @@ -177,49 +176,31 @@ impl ApplicationBuilder where S: 'static { /// /// fn main() { /// let app = Application::default("/") - /// .handler("/test", |req| { - /// match *req.method() { - /// Method::GET => httpcodes::HTTPOk, - /// Method::POST => httpcodes::HTTPMethodNotAllowed, - /// _ => httpcodes::HTTPNotFound, - /// } - /// }) + /// .route("/test", |r| r.f( + /// |req| { + /// match *req.method() { + /// Method::GET => httpcodes::HTTPOk, + /// Method::POST => httpcodes::HTTPMethodNotAllowed, + /// _ => httpcodes::HTTPNotFound, + /// } + /// } + /// )) /// .finish(); /// } /// ``` - pub fn handler(&mut self, path: P, handler: F) -> &mut Self + pub fn route>(&mut self, path: P, f: F) -> &mut Self where P: Into, - F: Fn(HttpRequest) -> R + 'static, - R: FromRequest + 'static + F: FnOnce(&mut Route) + 'static { - self.parts.as_mut().expect("Use after finish") - .handlers.insert(path.into(), Box::new(WrapHandler::new(handler))); + { + let parts = self.parts.as_mut().expect("Use after finish"); + parts.routes.push((path.into(), Route::default())); + f(&mut parts.routes.last_mut().unwrap().1); + } self } - /// This method register handler for specified path prefix. - /// Any path that starts with this prefix matches handler. - pub fn route(&mut self, path: P, handler: H) -> &mut Self - where P: Into, H: Handler - { - self.parts.as_mut().expect("Use after finish") - .handlers.insert(path.into(), Box::new(WrapHandler::new(handler))); - self - } - - /// This method register async handler for specified path prefix. - /// Any path that starts with this prefix matches handler. - pub fn async(&mut self, path: P, handler: F) -> &mut Self - where F: Fn(HttpRequest) -> R + 'static, - R: Future + 'static, - P: Into, - { - self.parts.as_mut().expect("Use after finish") - .handlers.insert(path.into(), Box::new(AsyncHandler::new(handler))); - self - } - - /// Construct application + /// Register a middleware pub fn middleware(&mut self, mw: T) -> &mut Self where T: Middleware + 'static { @@ -232,27 +213,27 @@ impl ApplicationBuilder where S: 'static { pub fn finish(&mut self) -> Application { let parts = self.parts.take().expect("Use after finish"); - let mut handlers = HashMap::new(); let prefix = if parts.prefix.ends_with('/') { parts.prefix } else { parts.prefix + "/" }; - let mut routes = Vec::new(); + let mut resources = Vec::new(); for (path, handler) in parts.resources { - routes.push((path, handler)) + resources.push((path, handler)) } - for (path, handler) in parts.handlers { - handlers.insert(prefix.clone() + path.trim_left_matches('/'), handler); + let mut routes = Vec::new(); + for (path, route) in parts.routes { + routes.push((prefix.clone() + path.trim_left_matches('/'), route)); } Application { state: Rc::new(parts.state), prefix: prefix.clone(), default: parts.default, - handlers: handlers, - router: RouteRecognizer::new(prefix, routes), + routes: routes, + router: RouteRecognizer::new(prefix, resources), middlewares: Rc::new(parts.middlewares), } } diff --git a/src/dev.rs b/src/dev.rs index 7e597c9d..70f654b2 100644 --- a/src/dev.rs +++ b/src/dev.rs @@ -9,7 +9,7 @@ //! ``` // dev specific -pub use route::Handler; +pub use handler::Handler; pub use pipeline::Pipeline; pub use channel::{HttpChannel, HttpHandler}; pub use recognizer::{FromParam, RouteRecognizer}; diff --git a/src/fs.rs b/src/fs.rs index df275ea8..1bf678ee 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -9,7 +9,7 @@ use std::path::{Path, PathBuf}; use std::ops::{Deref, DerefMut}; use mime_guess::get_mime_type; -use route::{Handler, FromRequest}; +use handler::{Handler, FromRequest}; use recognizer::FromParam; use httprequest::HttpRequest; use httpresponse::HttpResponse; @@ -198,7 +198,7 @@ impl FromRequest for FilesystemElement { /// /// fn main() { /// let app = actix_web::Application::default("/") -/// .route("/static", actix_web::fs::StaticFiles::new(".", true)) +/// .route("/static", |r| r.h(actix_web::fs::StaticFiles::new(".", true))) /// .finish(); /// } /// ``` diff --git a/src/route.rs b/src/handler.rs similarity index 100% rename from src/route.rs rename to src/handler.rs diff --git a/src/httpcodes.rs b/src/httpcodes.rs index 5aa43b05..e2af3ec5 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, Handler, RouteHandler, FromRequest}; +use handler::{Reply, Handler, RouteHandler, FromRequest}; use httprequest::HttpRequest; use httpresponse::{HttpResponse, HttpResponseBuilder}; diff --git a/src/httpresponse.rs b/src/httpresponse.rs index cfb83fa0..4a447abe 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -11,7 +11,7 @@ use serde::Serialize; use Cookie; use body::Body; use error::Error; -use route::FromRequest; +use handler::FromRequest; use encoding::ContentEncoding; use httprequest::HttpRequest; diff --git a/src/lib.rs b/src/lib.rs index cc69995a..070514ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,7 @@ mod httpresponse; mod payload; mod resource; mod recognizer; -mod route; +mod handler; mod pipeline; mod server; mod channel; @@ -83,7 +83,7 @@ pub use application::Application; pub use httprequest::{HttpRequest, UrlEncoded}; pub use httpresponse::HttpResponse; pub use payload::{Payload, PayloadItem}; -pub use route::{Reply, Json, FromRequest}; +pub use handler::{Reply, Json, FromRequest}; pub use resource::{Route, Resource}; pub use recognizer::Params; pub use server::HttpServer; diff --git a/src/pipeline.rs b/src/pipeline.rs index 85473fc7..4c9c7936 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -8,7 +8,7 @@ use futures::task::{Task as FutureTask, current as current_task}; use body::{Body, BodyStream}; use context::{Frame, IoContext}; use error::{Error, UnexpectedTaskFrame}; -use route::{Reply, ReplyItem}; +use handler::{Reply, ReplyItem}; use h1writer::{Writer, WriterState}; use httprequest::HttpRequest; use httpresponse::HttpResponse; diff --git a/src/resource.rs b/src/resource.rs index fd669210..a7b41d56 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -5,7 +5,7 @@ use futures::Future; use error::Error; use pred::{self, Predicate}; -use route::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler}; +use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler}; use httpcodes::HTTPNotFound; use httprequest::HttpRequest; use httpresponse::HttpResponse; @@ -31,7 +31,7 @@ impl Default for Route { impl Route { - fn check(&self, req: &mut HttpRequest) -> bool { + pub(crate) fn check(&self, req: &mut HttpRequest) -> bool { for pred in &self.preds { if !pred.check(req) { return false @@ -40,7 +40,7 @@ impl Route { true } - fn handle(&self, req: HttpRequest) -> Reply { + pub(crate) fn handle(&self, req: HttpRequest) -> Reply { self.handler.handle(req) } diff --git a/src/ws.rs b/src/ws.rs index 6c6f5822..21b630be 100644 --- a/src/ws.rs +++ b/src/ws.rs @@ -56,7 +56,7 @@ use actix::{Actor, AsyncContext, ResponseType, StreamHandler}; use body::Body; use context::HttpContext; -use route::Reply; +use handler::Reply; use payload::Payload; use error::{Error, WsHandshakeError}; use httprequest::HttpRequest;