From 237677be15d00b6074b18eb214790ccbd21eb349 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 3 Mar 2019 12:09:38 -0800 Subject: [PATCH] rename filter to guard --- src/{filter.rs => guard.rs} | 139 +++++++++++---------- src/lib.rs | 2 +- src/resource.rs | 51 ++++---- src/route.rs | 243 ++++++++---------------------------- 4 files changed, 145 insertions(+), 290 deletions(-) rename src/{filter.rs => guard.rs} (67%) diff --git a/src/filter.rs b/src/guard.rs similarity index 67% rename from src/filter.rs rename to src/guard.rs index 501c60d83..10a56921a 100644 --- a/src/filter.rs +++ b/src/guard.rs @@ -1,47 +1,48 @@ -//! Route match predicates +//! Route match guards. #![allow(non_snake_case)] use actix_http::http::{self, header, HttpTryFrom}; use actix_http::RequestHead; -/// Trait defines resource predicate. -/// Predicate can modify request object. It is also possible to +/// Trait defines resource guards. Guards are used for routes selection. +/// +/// Guard can not modify request object. But it is possible to /// to store extra attributes on request by using `Extensions` container, -/// Extensions container available via `HttpRequest::extensions()` method. -pub trait Filter { +/// Extensions container available via `RequestHead::extensions()` method. +pub trait Guard { /// Check if request matches predicate fn check(&self, request: &RequestHead) -> bool; } -/// Return filter that matches if any of supplied filters. +/// Return guard that matches if any of supplied guards. /// /// ```rust -/// use actix_web::{web, filter, App, HttpResponse}; +/// use actix_web::{web, guard, App, HttpResponse}; /// /// fn main() { /// App::new().resource("/index.html", |r| /// r.route( /// web::route() -/// .filter(filter::Any(filter::Get()).or(filter::Post())) +/// .guard(guard::Any(guard::Get()).or(guard::Post())) /// .to(|| HttpResponse::MethodNotAllowed())) /// ); /// } /// ``` -pub fn Any(filter: F) -> AnyFilter { - AnyFilter(vec![Box::new(filter)]) +pub fn Any(guard: F) -> AnyGuard { + AnyGuard(vec![Box::new(guard)]) } -/// Matches if any of supplied filters matche. -pub struct AnyFilter(Vec>); +/// Matches if any of supplied guards matche. +pub struct AnyGuard(Vec>); -impl AnyFilter { - /// Add filter to a list of filters to check - pub fn or(mut self, filter: F) -> Self { - self.0.push(Box::new(filter)); +impl AnyGuard { + /// Add guard to a list of guards to check + pub fn or(mut self, guard: F) -> Self { + self.0.push(Box::new(guard)); self } } -impl Filter for AnyFilter { +impl Guard for AnyGuard { fn check(&self, req: &RequestHead) -> bool { for p in &self.0 { if p.check(req) { @@ -52,37 +53,37 @@ impl Filter for AnyFilter { } } -/// Return filter that matches if all of supplied filters match. +/// Return guard that matches if all of the supplied guards. /// /// ```rust /// # extern crate actix_web; -/// use actix_web::{filter, web, App, HttpResponse}; +/// use actix_web::{guard, web, App, HttpResponse}; /// /// fn main() { /// App::new().resource("/index.html", |r| { /// r.route(web::route() -/// .filter( -/// filter::All(filter::Get()).and(filter::Header("content-type", "text/plain"))) +/// .guard( +/// guard::All(guard::Get()).and(guard::Header("content-type", "text/plain"))) /// .to(|| HttpResponse::MethodNotAllowed())) /// }); /// } /// ``` -pub fn All(filter: F) -> AllFilter { - AllFilter(vec![Box::new(filter)]) +pub fn All(guard: F) -> AllGuard { + AllGuard(vec![Box::new(guard)]) } -/// Matches if all of supplied filters matche. -pub struct AllFilter(Vec>); +/// Matches if all of supplied guards. +pub struct AllGuard(Vec>); -impl AllFilter { - /// Add new predicate to list of predicates to check - pub fn and(mut self, filter: F) -> Self { - self.0.push(Box::new(filter)); +impl AllGuard { + /// Add new guard to the list of guards to check + pub fn and(mut self, guard: F) -> Self { + self.0.push(Box::new(guard)); self } } -impl Filter for AllFilter { +impl Guard for AllGuard { fn check(&self, request: &RequestHead) -> bool { for p in &self.0 { if !p.check(request) { @@ -93,93 +94,93 @@ impl Filter for AllFilter { } } -/// Return predicate that matches if supplied predicate does not match. -pub fn Not(filter: F) -> NotFilter { - NotFilter(Box::new(filter)) +/// Return guard that matches if supplied guard does not match. +pub fn Not(guard: F) -> NotGuard { + NotGuard(Box::new(guard)) } #[doc(hidden)] -pub struct NotFilter(Box); +pub struct NotGuard(Box); -impl Filter for NotFilter { +impl Guard for NotGuard { fn check(&self, request: &RequestHead) -> bool { !self.0.check(request) } } -/// Http method predicate +/// Http method guard #[doc(hidden)] -pub struct MethodFilter(http::Method); +pub struct MethodGuard(http::Method); -impl Filter for MethodFilter { +impl Guard for MethodGuard { fn check(&self, request: &RequestHead) -> bool { request.method == self.0 } } -/// Predicate to match *GET* http method -pub fn Get() -> MethodFilter { - MethodFilter(http::Method::GET) +/// Guard to match *GET* http method +pub fn Get() -> MethodGuard { + MethodGuard(http::Method::GET) } /// Predicate to match *POST* http method -pub fn Post() -> MethodFilter { - MethodFilter(http::Method::POST) +pub fn Post() -> MethodGuard { + MethodGuard(http::Method::POST) } /// Predicate to match *PUT* http method -pub fn Put() -> MethodFilter { - MethodFilter(http::Method::PUT) +pub fn Put() -> MethodGuard { + MethodGuard(http::Method::PUT) } /// Predicate to match *DELETE* http method -pub fn Delete() -> MethodFilter { - MethodFilter(http::Method::DELETE) +pub fn Delete() -> MethodGuard { + MethodGuard(http::Method::DELETE) } /// Predicate to match *HEAD* http method -pub fn Head() -> MethodFilter { - MethodFilter(http::Method::HEAD) +pub fn Head() -> MethodGuard { + MethodGuard(http::Method::HEAD) } /// Predicate to match *OPTIONS* http method -pub fn Options() -> MethodFilter { - MethodFilter(http::Method::OPTIONS) +pub fn Options() -> MethodGuard { + MethodGuard(http::Method::OPTIONS) } /// Predicate to match *CONNECT* http method -pub fn Connect() -> MethodFilter { - MethodFilter(http::Method::CONNECT) +pub fn Connect() -> MethodGuard { + MethodGuard(http::Method::CONNECT) } /// Predicate to match *PATCH* http method -pub fn Patch() -> MethodFilter { - MethodFilter(http::Method::PATCH) +pub fn Patch() -> MethodGuard { + MethodGuard(http::Method::PATCH) } /// Predicate to match *TRACE* http method -pub fn Trace() -> MethodFilter { - MethodFilter(http::Method::TRACE) +pub fn Trace() -> MethodGuard { + MethodGuard(http::Method::TRACE) } /// Predicate to match specified http method -pub fn Method(method: http::Method) -> MethodFilter { - MethodFilter(method) +pub fn Method(method: http::Method) -> MethodGuard { + MethodGuard(method) } /// Return predicate that matches if request contains specified header and /// value. -pub fn Header(name: &'static str, value: &'static str) -> HeaderFilter { - HeaderFilter( +pub fn Header(name: &'static str, value: &'static str) -> HeaderGuard { + HeaderGuard( header::HeaderName::try_from(name).unwrap(), header::HeaderValue::from_static(value), ) } #[doc(hidden)] -pub struct HeaderFilter(header::HeaderName, header::HeaderValue); +pub struct HeaderGuard(header::HeaderName, header::HeaderValue); -impl Filter for HeaderFilter { +impl Guard for HeaderGuard { fn check(&self, req: &RequestHead) -> bool { if let Some(val) = req.headers.get(&self.0) { return val == self.1; @@ -197,26 +198,26 @@ impl Filter for HeaderFilter { // /// fn main() { // /// App::new().resource("/index.html", |r| { // /// r.route() -// /// .filter(pred::Host("www.rust-lang.org")) +// /// .guard(pred::Host("www.rust-lang.org")) // /// .f(|_| HttpResponse::MethodNotAllowed()) // /// }); // /// } // /// ``` -// pub fn Host>(host: H) -> HostFilter { -// HostFilter(host.as_ref().to_string(), None) +// pub fn Host>(host: H) -> HostGuard { +// HostGuard(host.as_ref().to_string(), None) // } // #[doc(hidden)] -// pub struct HostFilter(String, Option); +// pub struct HostGuard(String, Option); -// impl HostFilter { +// impl HostGuard { // /// Set reuest scheme to match // pub fn scheme>(&mut self, scheme: H) { // self.1 = Some(scheme.as_ref().to_string()) // } // } -// impl Filter for HostFilter { +// impl Guard for HostGuard { // fn check(&self, _req: &RequestHead) -> bool { // // let info = req.connection_info(); // // if let Some(ref scheme) = self.1 { diff --git a/src/lib.rs b/src/lib.rs index 8ad689aa9..e876a7ea4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ pub mod extractor; pub mod handler; // mod info; pub mod blocking; -pub mod filter; +pub mod guard; pub mod middleware; mod request; mod resource; diff --git a/src/resource.rs b/src/resource.rs index 0bee0ecd4..98c2dc114 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -56,22 +56,21 @@ where InitError = (), >, { - /// Register a new route and return mutable reference to *Route* object. - /// *Route* is used for route configuration, i.e. adding predicates, + /// Register a new route. + /// *Route* is used for route configuration, i.e. adding guards, /// setting up handler. /// - /// ```rust,ignore - /// use actix_web::*; + /// ```rust + /// use actix_web::{web, guard, App, HttpResponse}; /// /// fn main() { /// let app = App::new() /// .resource("/", |r| { - /// r.route() - /// .filter(pred::Any(pred::Get()).or(pred::Put())) - /// .filter(pred::Header("Content-Type", "text/plain")) - /// .f(|r| HttpResponse::Ok()) - /// }) - /// .finish(); + /// r.route(web::route() + /// .guard(guard::Any(guard::Get()).or(guard::Put())) + /// .guard(guard::Header("Content-Type", "text/plain")) + /// .to(|| HttpResponse::Ok())) + /// }); /// } /// ``` pub fn route(mut self, route: Route

) -> Self { @@ -81,21 +80,23 @@ where /// Register a new route and add handler. /// - /// ```rust,ignore - /// # extern crate actix_web; + /// ```rust /// use actix_web::*; - /// fn index(req: HttpRequest) -> HttpResponse { unimplemented!() } /// - /// App::new().resource("/", |r| r.with(index)); + /// fn index(req: HttpRequest) -> HttpResponse { + /// unimplemented!() + /// } + /// + /// App::new().resource("/", |r| r.to(index)); /// ``` /// /// This is shortcut for: /// - /// ```rust,ignore + /// ```rust /// # extern crate actix_web; /// # use actix_web::*; /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() } - /// App::new().resource("/", |r| r.route().with(index)); + /// App::new().resource("/", |r| r.route(web::route().to(index))); /// ``` pub fn to(mut self, handler: F) -> Self where @@ -109,30 +110,26 @@ where /// Register a new route and add async handler. /// - /// ```rust,ignore - /// # extern crate actix_web; - /// # extern crate futures; + /// ```rust /// use actix_web::*; - /// use futures::future::Future; + /// use futures::future::{ok, Future}; /// - /// fn index(req: HttpRequest) -> Box> { - /// unimplemented!() + /// fn index(req: HttpRequest) -> impl Future { + /// ok(HttpResponse::Ok().finish()) /// } /// - /// App::new().resource("/", |r| r.with_async(index)); + /// App::new().resource("/", |r| r.to_async(index)); /// ``` /// /// This is shortcut for: /// - /// ```rust,ignore - /// # extern crate actix_web; - /// # extern crate futures; + /// ```rust /// # use actix_web::*; /// # use futures::future::Future; /// # fn index(req: HttpRequest) -> Box> { /// # unimplemented!() /// # } - /// App::new().resource("/", |r| r.route().with_async(index)); + /// App::new().resource("/", |r| r.route(web::route().to_async(index))); /// ``` #[allow(clippy::wrong_self_convention)] pub fn to_async(mut self, handler: F) -> Self diff --git a/src/route.rs b/src/route.rs index 578ba79ef..16a4fc5ba 100644 --- a/src/route.rs +++ b/src/route.rs @@ -5,7 +5,7 @@ use actix_http::{http::Method, Error, Extensions, Response}; use actix_service::{NewService, Service}; use futures::{Async, Future, IntoFuture, Poll}; -use crate::filter::{self, Filter}; +use crate::guard::{self, Guard}; use crate::handler::{ AsyncFactory, AsyncHandle, ConfigStorage, Extract, ExtractorConfig, Factory, FromRequest, Handle, @@ -40,7 +40,7 @@ type BoxedRouteNewService = Box< /// If handler is not explicitly set, default *404 Not Found* handler is used. pub struct Route

{ service: BoxedRouteNewService, ServiceResponse>, - filters: Rc>>, + guards: Rc>>, config: ConfigStorage, config_ref: Rc>>>, } @@ -55,7 +55,7 @@ impl Route

{ Handle::new(|| HttpResponse::NotFound()).map_err(|_| panic!()), ), )), - filters: Rc::new(Vec::new()), + guards: Rc::new(Vec::new()), config: ConfigStorage::default(), config_ref, } @@ -98,7 +98,7 @@ impl

NewService for Route

{ fn new_service(&self, _: &()) -> Self::Future { CreateRouteService { fut: self.service.new_service(&()), - filters: self.filters.clone(), + guards: self.guards.clone(), } } } @@ -109,7 +109,7 @@ type RouteFuture

= Box< pub struct CreateRouteService

{ fut: RouteFuture

, - filters: Rc>>, + guards: Rc>>, } impl

Future for CreateRouteService

{ @@ -120,7 +120,7 @@ impl

Future for CreateRouteService

{ match self.fut.poll()? { Async::Ready(service) => Ok(Async::Ready(RouteService { service, - filters: self.filters.clone(), + guards: self.guards.clone(), })), Async::NotReady => Ok(Async::NotReady), } @@ -129,12 +129,12 @@ impl

Future for CreateRouteService

{ pub struct RouteService

{ service: BoxedRouteService, ServiceResponse>, - filters: Rc>>, + guards: Rc>>, } impl

RouteService

{ pub fn check(&self, req: &mut ServiceRequest

) -> bool { - for f in self.filters.iter() { + for f in self.guards.iter() { if !f.check(req.head()) { return false; } @@ -159,45 +159,41 @@ impl

Service for RouteService

{ } impl Route

{ - /// Add method match filter to the route. + /// Add method guard to the route. /// - /// ```rust,ignore - /// # extern crate actix_web; + /// ```rust /// # use actix_web::*; /// # fn main() { /// App::new().resource("/path", |r| { - /// r.route() - /// .filter(pred::Get()) - /// .filter(pred::Header("content-type", "text/plain")) - /// .f(|req| HttpResponse::Ok()) - /// }) - /// # .finish(); + /// r.route(web::get() + /// .guard(guard::Get()) + /// .guard(guard::Header("content-type", "text/plain")) + /// .to(|req: HttpRequest| HttpResponse::Ok())) + /// }); /// # } /// ``` pub fn method(mut self, method: Method) -> Self { - Rc::get_mut(&mut self.filters) + Rc::get_mut(&mut self.guards) .unwrap() - .push(Box::new(filter::Method(method))); + .push(Box::new(guard::Method(method))); self } - /// Add filter to the route. + /// Add guard to the route. /// - /// ```rust,ignore - /// # extern crate actix_web; + /// ```rust /// # use actix_web::*; /// # fn main() { /// App::new().resource("/path", |r| { - /// r.route() - /// .filter(pred::Get()) - /// .filter(pred::Header("content-type", "text/plain")) - /// .f(|req| HttpResponse::Ok()) - /// }) - /// # .finish(); + /// r.route(web::route() + /// .guard(guard::Get()) + /// .guard(guard::Header("content-type", "text/plain")) + /// .to(|req: HttpRequest| HttpResponse::Ok())) + /// }); /// # } /// ``` - pub fn filter(mut self, f: F) -> Self { - Rc::get_mut(&mut self.filters).unwrap().push(Box::new(f)); + pub fn guard(mut self, f: F) -> Self { + Rc::get_mut(&mut self.guards).unwrap().push(Box::new(f)); self } @@ -214,19 +210,16 @@ impl Route

{ // { // RouteServiceBuilder { // service: md.into_new_service(), - // filters: self.filters, + // guards: self.guards, // _t: PhantomData, // } // } - /// Set handler function, use request extractor for parameters. + /// Set handler function, use request extractors for parameters. /// - /// ```rust,ignore - /// # extern crate bytes; - /// # extern crate actix_web; - /// # extern crate futures; + /// ```rust /// #[macro_use] extern crate serde_derive; - /// use actix_web::{http, App, Path, Result}; + /// use actix_web::{web, http, App, Path}; /// /// #[derive(Deserialize)] /// struct Info { @@ -234,27 +227,24 @@ impl Route

{ /// } /// /// /// extract path info using serde - /// fn index(info: Path) -> Result { - /// Ok(format!("Welcome {}!", info.username)) + /// fn index(info: Path) -> String { + /// format!("Welcome {}!", info.username) /// } /// /// fn main() { /// let app = App::new().resource( /// "/{username}/index.html", // <- define path parameters - /// |r| r.method(http::Method::GET).with(index), - /// ); // <- use `with` extractor + /// |r| r.route(web::get().to(index)), // <- register handler + /// ); /// } /// ``` /// /// It is possible to use multiple extractors for one handler function. /// - /// ```rust,ignore - /// # extern crate bytes; - /// # extern crate actix_web; - /// # extern crate futures; - /// #[macro_use] extern crate serde_derive; + /// ```rust /// # use std::collections::HashMap; - /// use actix_web::{http, App, Json, Path, Query, Result}; + /// # use serde_derive::Deserialize; + /// use actix_web::{web, http, App, Json, Path, Query}; /// /// #[derive(Deserialize)] /// struct Info { @@ -262,17 +252,15 @@ impl Route

{ /// } /// /// /// extract path info using serde - /// fn index( - /// path: Path, query: Query>, body: Json, - /// ) -> Result { - /// Ok(format!("Welcome {}!", path.username)) + /// fn index(path: Path, query: Query>, body: Json) -> String { + /// format!("Welcome {}!", path.username) /// } /// /// fn main() { /// let app = App::new().resource( /// "/{username}/index.html", // <- define path parameters - /// |r| r.method(http::Method::GET).with(index), - /// ); // <- use `with` extractor + /// |r| r.route(web::method(http::Method::GET).to(index)), + /// ); /// } /// ``` pub fn to(mut self, handler: F) -> Route

@@ -289,16 +277,13 @@ impl Route

{ self } - /// Set async handler function, use request extractor for parameters. - /// Also this method needs to be used if your handler function returns - /// `impl Future<>` + /// Set async handler function, use request extractors for parameters. + /// This method has to be used if your handler function returns `impl Future<>` /// - /// ```rust,ignore - /// # extern crate bytes; - /// # extern crate actix_web; - /// # extern crate futures; + /// ```rust + /// # use futures::future::ok; /// #[macro_use] extern crate serde_derive; - /// use actix_web::{http, App, Error, Path}; + /// use actix_web::{web, http, App, Error, Path}; /// use futures::Future; /// /// #[derive(Deserialize)] @@ -307,15 +292,15 @@ impl Route

{ /// } /// /// /// extract path info using serde - /// fn index(info: Path) -> Box> { - /// unimplemented!() + /// fn index(info: Path) -> impl Future { + /// ok("Hello World!") /// } /// /// fn main() { /// let app = App::new().resource( /// "/{username}/index.html", // <- define path parameters - /// |r| r.method(http::Method::GET).with_async(index), - /// ); // <- use `with` extractor + /// |r| r.route(web::get().to_async(index)), // <- register async handler + /// ); /// } /// ``` #[allow(clippy::wrong_self_convention)] @@ -363,134 +348,6 @@ impl Route

{ } } -// pub struct RouteServiceBuilder { -// service: T, -// filters: Vec>, -// _t: PhantomData<(P, U1, U2)>, -// } - -// impl RouteServiceBuilder -// where -// T: NewService< -// Request = HandlerRequest, -// Response = HandlerRequest, -// Error = Error, -// InitError = (), -// >, -// { -// pub fn new>(factory: F) -> Self { -// RouteServiceBuilder { -// service: factory.into_new_service(), -// filters: Vec::new(), -// _t: PhantomData, -// } -// } - -// /// Add method match filter to the route. -// /// -// /// ```rust -// /// # extern crate actix_web; -// /// # use actix_web::*; -// /// # fn main() { -// /// App::new().resource("/path", |r| { -// /// r.route() -// /// .filter(pred::Get()) -// /// .filter(pred::Header("content-type", "text/plain")) -// /// .f(|req| HttpResponse::Ok()) -// /// }) -// /// # .finish(); -// /// # } -// /// ``` -// pub fn method(mut self, method: Method) -> Self { -// self.filters.push(Box::new(filter::Method(method))); -// self -// } - -// /// Add filter to the route. -// /// -// /// ```rust -// /// # extern crate actix_web; -// /// # use actix_web::*; -// /// # fn main() { -// /// App::new().resource("/path", |r| { -// /// r.route() -// /// .filter(pred::Get()) -// /// .filter(pred::Header("content-type", "text/plain")) -// /// .f(|req| HttpResponse::Ok()) -// /// }) -// /// # .finish(); -// /// # } -// /// ``` -// pub fn filter + 'static>(&mut self, f: F) -> &mut Self { -// self.filters.push(Box::new(f)); -// self -// } - -// pub fn map>( -// self, -// md: F, -// ) -> RouteServiceBuilder< -// impl NewService< -// Request = HandlerRequest, -// Response = HandlerRequest, -// Error = Error, -// InitError = (), -// >, -// S, -// U1, -// U2, -// > -// where -// T1: NewService< -// Request = HandlerRequest, -// Response = HandlerRequest, -// InitError = (), -// >, -// T1::Error: Into, -// { -// RouteServiceBuilder { -// service: self -// .service -// .and_then(md.into_new_service().map_err(|e| e.into())), -// filters: self.filters, -// _t: PhantomData, -// } -// } - -// pub fn to_async(self, handler: F) -> Route -// where -// F: AsyncFactory, -// P: FromRequest + 'static, -// R: IntoFuture, -// R::Item: Into, -// R::Error: Into, -// { -// Route { -// service: self -// .service -// .and_then(Extract::new(P::Config::default())) -// .then(AsyncHandle::new(handler)), -// filters: Rc::new(self.filters), -// } -// } - -// pub fn to(self, handler: F) -> Route -// where -// F: Factory + 'static, -// P: FromRequest + 'static, -// R: Responder + 'static, -// { -// Route { -// service: Box::new(RouteNewService::new( -// self.service -// .and_then(Extract::new(P::Config::default())) -// .and_then(Handle::new(handler)), -// )), -// filters: Rc::new(self.filters), -// } -// } -// } - struct RouteNewService where T: NewService, Error = (Error, ServiceFromRequest

)>,