1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

rename filter to guard

This commit is contained in:
Nikolay Kim 2019-03-03 12:09:38 -08:00
parent b81ae899f6
commit 237677be15
4 changed files with 145 additions and 290 deletions

View File

@ -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<F: Filter + 'static>(filter: F) -> AnyFilter {
AnyFilter(vec![Box::new(filter)])
pub fn Any<F: Guard + 'static>(guard: F) -> AnyGuard {
AnyGuard(vec![Box::new(guard)])
}
/// Matches if any of supplied filters matche.
pub struct AnyFilter(Vec<Box<Filter>>);
/// Matches if any of supplied guards matche.
pub struct AnyGuard(Vec<Box<Guard>>);
impl AnyFilter {
/// Add filter to a list of filters to check
pub fn or<F: Filter + 'static>(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<F: Guard + 'static>(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<F: Filter + 'static>(filter: F) -> AllFilter {
AllFilter(vec![Box::new(filter)])
pub fn All<F: Guard + 'static>(guard: F) -> AllGuard {
AllGuard(vec![Box::new(guard)])
}
/// Matches if all of supplied filters matche.
pub struct AllFilter(Vec<Box<Filter>>);
/// Matches if all of supplied guards.
pub struct AllGuard(Vec<Box<Guard>>);
impl AllFilter {
/// Add new predicate to list of predicates to check
pub fn and<F: Filter + 'static>(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<F: Guard + 'static>(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<F: Filter + 'static>(filter: F) -> NotFilter {
NotFilter(Box::new(filter))
/// Return guard that matches if supplied guard does not match.
pub fn Not<F: Guard + 'static>(guard: F) -> NotGuard {
NotGuard(Box::new(guard))
}
#[doc(hidden)]
pub struct NotFilter(Box<Filter>);
pub struct NotGuard(Box<Guard>);
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<H: AsRef<str>>(host: H) -> HostFilter {
// HostFilter(host.as_ref().to_string(), None)
// pub fn Host<H: AsRef<str>>(host: H) -> HostGuard {
// HostGuard(host.as_ref().to_string(), None)
// }
// #[doc(hidden)]
// pub struct HostFilter(String, Option<String>);
// pub struct HostGuard(String, Option<String>);
// impl HostFilter {
// impl HostGuard {
// /// Set reuest scheme to match
// pub fn scheme<H: AsRef<str>>(&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 {

View File

@ -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;

View File

@ -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<P>) -> 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<F, I, R>(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<Future<Item=HttpResponse, Error=Error>> {
/// unimplemented!()
/// fn index(req: HttpRequest) -> impl Future<Item=HttpResponse, Error=Error> {
/// 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<Future<Item=HttpResponse, Error=Error>> {
/// # 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<F, I, R>(mut self, handler: F) -> Self

View File

@ -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<Req, Res> = Box<
/// If handler is not explicitly set, default *404 Not Found* handler is used.
pub struct Route<P> {
service: BoxedRouteNewService<ServiceRequest<P>, ServiceResponse>,
filters: Rc<Vec<Box<Filter>>>,
guards: Rc<Vec<Box<Guard>>>,
config: ConfigStorage,
config_ref: Rc<RefCell<Option<Rc<Extensions>>>>,
}
@ -55,7 +55,7 @@ impl<P: 'static> Route<P> {
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<P> NewService for Route<P> {
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<P> = Box<
pub struct CreateRouteService<P> {
fut: RouteFuture<P>,
filters: Rc<Vec<Box<Filter>>>,
guards: Rc<Vec<Box<Guard>>>,
}
impl<P> Future for CreateRouteService<P> {
@ -120,7 +120,7 @@ impl<P> Future for CreateRouteService<P> {
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<P> Future for CreateRouteService<P> {
pub struct RouteService<P> {
service: BoxedRouteService<ServiceRequest<P>, ServiceResponse>,
filters: Rc<Vec<Box<Filter>>>,
guards: Rc<Vec<Box<Guard>>>,
}
impl<P> RouteService<P> {
pub fn check(&self, req: &mut ServiceRequest<P>) -> 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<P> Service for RouteService<P> {
}
impl<P: 'static> Route<P> {
/// 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<F: Filter + 'static>(mut self, f: F) -> Self {
Rc::get_mut(&mut self.filters).unwrap().push(Box::new(f));
pub fn guard<F: Guard + 'static>(mut self, f: F) -> Self {
Rc::get_mut(&mut self.guards).unwrap().push(Box::new(f));
self
}
@ -214,19 +210,16 @@ impl<P: 'static> Route<P> {
// {
// 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<P: 'static> Route<P> {
/// }
///
/// /// extract path info using serde
/// fn index(info: Path<Info>) -> Result<String> {
/// Ok(format!("Welcome {}!", info.username))
/// fn index(info: Path<Info>) -> 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<P: 'static> Route<P> {
/// }
///
/// /// extract path info using serde
/// fn index(
/// path: Path<Info>, query: Query<HashMap<String, String>>, body: Json<Info>,
/// ) -> Result<String> {
/// Ok(format!("Welcome {}!", path.username))
/// fn index(path: Path<Info>, query: Query<HashMap<String, String>>, body: Json<Info>) -> 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<F, T, R>(mut self, handler: F) -> Route<P>
@ -289,16 +277,13 @@ impl<P: 'static> Route<P> {
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<P: 'static> Route<P> {
/// }
///
/// /// extract path info using serde
/// fn index(info: Path<Info>) -> Box<Future<Item = &'static str, Error = Error>> {
/// unimplemented!()
/// fn index(info: Path<Info>) -> impl Future<Item = &'static str, Error = Error> {
/// 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<P: 'static> Route<P> {
}
}
// pub struct RouteServiceBuilder<P, T, U1, U2> {
// service: T,
// filters: Vec<Box<Filter>>,
// _t: PhantomData<(P, U1, U2)>,
// }
// impl<T, S: 'static, U1, U2> RouteServiceBuilder<T, S, U1, U2>
// where
// T: NewService<
// Request = HandlerRequest<S, U1>,
// Response = HandlerRequest<S, U2>,
// Error = Error,
// InitError = (),
// >,
// {
// pub fn new<F: IntoNewService<T>>(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<F: Filter<S> + 'static>(&mut self, f: F) -> &mut Self {
// self.filters.push(Box::new(f));
// self
// }
// pub fn map<T1, U3, F: IntoNewService<T1>>(
// self,
// md: F,
// ) -> RouteServiceBuilder<
// impl NewService<
// Request = HandlerRequest<S, U1>,
// Response = HandlerRequest<S, U3>,
// Error = Error,
// InitError = (),
// >,
// S,
// U1,
// U2,
// >
// where
// T1: NewService<
// Request = HandlerRequest<S, U2>,
// Response = HandlerRequest<S, U3>,
// InitError = (),
// >,
// T1::Error: Into<Error>,
// {
// RouteServiceBuilder {
// service: self
// .service
// .and_then(md.into_new_service().map_err(|e| e.into())),
// filters: self.filters,
// _t: PhantomData,
// }
// }
// pub fn to_async<F, P, R>(self, handler: F) -> Route<S>
// where
// F: AsyncFactory<S, U2, P, R>,
// P: FromRequest<S> + 'static,
// R: IntoFuture,
// R::Item: Into<Response>,
// R::Error: Into<Error>,
// {
// Route {
// service: self
// .service
// .and_then(Extract::new(P::Config::default()))
// .then(AsyncHandle::new(handler)),
// filters: Rc::new(self.filters),
// }
// }
// pub fn to<F, P, R>(self, handler: F) -> Route<S>
// where
// F: Factory<S, U2, P, R> + 'static,
// P: FromRequest<S> + 'static,
// R: Responder<S> + '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<P, T>
where
T: NewService<Request = ServiceRequest<P>, Error = (Error, ServiceFromRequest<P>)>,