From 368730f5f10b2cc5ad29793ea765bbb0cef8982d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 29 Apr 2018 19:35:50 -0700 Subject: [PATCH] Add route scopes #202 --- CHANGES.md | 2 ++ src/application.rs | 50 ++++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 2 ++ src/route.rs | 3 ++- src/server/h1.rs | 6 +----- 5 files changed, 53 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a771ce37a..8d3861a32 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## 0.6.0 (...) +* Add route scopes #202 + * Websocket CloseCode Empty/Status is ambiguous #193 * Add Content-Disposition to NamedFile #204 diff --git a/src/application.rs b/src/application.rs index 4ee5157d5..7de2a2588 100644 --- a/src/application.rs +++ b/src/application.rs @@ -2,8 +2,7 @@ use std::cell::UnsafeCell; use std::collections::HashMap; use std::rc::Rc; -use handler::Reply; -use handler::{FromRequest, Handler, Responder, RouteHandler, WrapHandler}; +use handler::{FromRequest, Handler, Reply, Responder, RouteHandler, WrapHandler}; use header::ContentEncoding; use http::Method; use httprequest::HttpRequest; @@ -11,6 +10,7 @@ use middleware::Middleware; use pipeline::{HandlerType, Pipeline, PipelineHandler}; use resource::ResourceHandler; use router::{Resource, Router}; +use scope::Scope; use server::{HttpHandler, HttpHandlerTask, IntoHttpHandler, ServerSettings}; #[deprecated(since = "0.5.0", note = "please use `actix_web::App` instead")] @@ -76,9 +76,9 @@ impl HttpApplication { &*(&req.path()[inner.prefix + prefix.len()..] as *const _) }; if path.is_empty() { - req.match_info_mut().add("tail", ""); + req.match_info_mut().add("tail", "/"); } else { - req.match_info_mut().add("tail", path.split_at(1).1); + req.match_info_mut().add("tail", path); } return HandlerType::Handler(idx); } @@ -300,6 +300,48 @@ where self } + /// Configure scope for common root path. + /// + /// Scopes collect multiple paths under a common path prefix. + /// Scope path can not contain variable path segments as resources. + /// + /// ```rust + /// # extern crate actix_web; + /// use actix_web::{http, App, HttpRequest, HttpResponse}; + /// + /// fn main() { + /// let app = App::new() + /// .scope("/app", |scope| { + /// scope.resource("/path1", |r| r.f(|_| HttpResponse::Ok())) + /// .resource("/path2", |r| r.f(|_| HttpResponse::Ok())) + /// .resource("/path3", |r| r.f(|_| HttpResponse::MethodNotAllowed())) + /// }); + /// } + /// ``` + /// + /// In the above example three routes get registered: + /// * /app/path1 - reponds to all http method + /// * /app/path2 - `GET` requests + /// * /app/path3 - `HEAD` requests + /// + pub fn scope(mut self, path: &str, f: F) -> App + where + F: FnOnce(Scope) -> Scope, + { + { + let scope = Box::new(f(Scope::new())); + + let mut path = path.trim().trim_right_matches('/').to_owned(); + if !path.is_empty() && !path.starts_with('/') { + path.insert(0, '/') + } + let parts = self.parts.as_mut().expect("Use after finish"); + + parts.handlers.push((path, scope)); + } + self + } + /// Configure resource for a specific path. /// /// Resources may have variable path segments. For example, a diff --git a/src/lib.rs b/src/lib.rs index 431c60c1c..04371193e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,6 +149,7 @@ mod pipeline; mod resource; mod route; mod router; +mod scope; mod uri; mod with; @@ -171,6 +172,7 @@ pub use httpmessage::HttpMessage; pub use httprequest::HttpRequest; pub use httpresponse::HttpResponse; pub use json::Json; +pub use scope::Scope; #[doc(hidden)] pub mod httpcodes; diff --git a/src/route.rs b/src/route.rs index 681ee1cb9..27f0133b0 100644 --- a/src/route.rs +++ b/src/route.rs @@ -1,8 +1,9 @@ -use futures::{Async, Future, Poll}; use std::cell::UnsafeCell; use std::marker::PhantomData; use std::rc::Rc; +use futures::{Async, Future, Poll}; + use error::Error; use handler::{AsyncHandler, FromRequest, Handler, Reply, ReplyItem, Responder, RouteHandler, WrapHandler}; diff --git a/src/server/h1.rs b/src/server/h1.rs index f420ecb77..5f70bd0dc 100644 --- a/src/server/h1.rs +++ b/src/server/h1.rs @@ -388,11 +388,7 @@ where } } Err(e) => { - return if e.kind() == io::ErrorKind::WouldBlock { - false - } else { - true - }; + return e.kind() == io::ErrorKind::WouldBlock; } } }