mirror of https://github.com/fafhrd91/actix-web
optimize Route guards
This commit is contained in:
parent
1c95fc2654
commit
b187851a32
43
src/guard.rs
43
src/guard.rs
|
@ -38,6 +38,9 @@ use actix_http::RequestHead;
|
|||
pub trait Guard {
|
||||
/// Check if request matches predicate
|
||||
fn check(&self, request: &RequestHead) -> bool;
|
||||
|
||||
/// Clone self into a new boxed guard.
|
||||
fn clone_guard(&self) -> Box<dyn Guard>;
|
||||
}
|
||||
|
||||
/// Create guard object for supplied function.
|
||||
|
@ -58,29 +61,37 @@ pub trait Guard {
|
|||
/// ```
|
||||
pub fn fn_guard<F>(f: F) -> impl Guard
|
||||
where
|
||||
F: Fn(&RequestHead) -> bool,
|
||||
F: Fn(&RequestHead) -> bool + Clone + 'static,
|
||||
{
|
||||
FnGuard(f)
|
||||
}
|
||||
|
||||
struct FnGuard<F: Fn(&RequestHead) -> bool>(F);
|
||||
struct FnGuard<F: Fn(&RequestHead) -> bool + Clone>(F);
|
||||
|
||||
impl<F> Guard for FnGuard<F>
|
||||
where
|
||||
F: Fn(&RequestHead) -> bool,
|
||||
F: Fn(&RequestHead) -> bool + Clone + 'static,
|
||||
{
|
||||
fn check(&self, head: &RequestHead) -> bool {
|
||||
(self.0)(head)
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(FnGuard(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Guard for F
|
||||
where
|
||||
F: Fn(&RequestHead) -> bool,
|
||||
F: Fn(&RequestHead) -> bool + Clone + 'static,
|
||||
{
|
||||
fn check(&self, head: &RequestHead) -> bool {
|
||||
(self)(head)
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(FnGuard(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return guard that matches if any of supplied guards.
|
||||
|
@ -120,6 +131,10 @@ impl Guard for AnyGuard {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(AnyGuard(self.0.iter().map(|g| g.clone_guard()).collect()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return guard that matches if all of the supplied guards.
|
||||
|
@ -160,6 +175,10 @@ impl Guard for AllGuard {
|
|||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(AllGuard(self.0.iter().map(|g| g.clone_guard()).collect()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return guard that matches if supplied guard does not match.
|
||||
|
@ -174,6 +193,10 @@ impl Guard for NotGuard {
|
|||
fn check(&self, request: &RequestHead) -> bool {
|
||||
!self.0.check(request)
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
self.0.clone_guard()
|
||||
}
|
||||
}
|
||||
|
||||
/// Http method guard
|
||||
|
@ -184,6 +207,10 @@ impl Guard for MethodGuard {
|
|||
fn check(&self, request: &RequestHead) -> bool {
|
||||
request.method == self.0
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(MethodGuard(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Guard to match *GET* http method
|
||||
|
@ -255,6 +282,10 @@ impl Guard for HeaderGuard {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(HeaderGuard(self.0.clone(), self.1.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return predicate that matches if request contains specified Host name.
|
||||
|
@ -319,6 +350,10 @@ impl Guard for HostGuard {
|
|||
|
||||
true
|
||||
}
|
||||
|
||||
fn clone_guard(&self) -> Box<dyn Guard> {
|
||||
Box::new(HostGuard(self.0.clone(), self.1.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
25
src/route.rs
25
src/route.rs
|
@ -2,7 +2,6 @@
|
|||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_http::{http::Method, Error};
|
||||
|
@ -43,7 +42,7 @@ type BoxedRouteNewService = Box<
|
|||
/// If handler is not explicitly set, default *404 Not Found* handler is used.
|
||||
pub struct Route {
|
||||
service: BoxedRouteNewService,
|
||||
guards: Rc<Vec<Box<dyn Guard>>>,
|
||||
guards: Vec<Box<dyn Guard>>,
|
||||
}
|
||||
|
||||
impl Route {
|
||||
|
@ -54,34 +53,34 @@ impl Route {
|
|||
service: Box::new(RouteNewService::new(HandlerService::new(|| {
|
||||
ready(HttpResponse::NotFound())
|
||||
}))),
|
||||
guards: Rc::new(Vec::new()),
|
||||
guards: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn take_guards(&mut self) -> Vec<Box<dyn Guard>> {
|
||||
std::mem::take(Rc::get_mut(&mut self.guards).unwrap())
|
||||
std::mem::take(&mut self.guards)
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceFactory<ServiceRequest> for Route {
|
||||
type Config = ();
|
||||
type Response = ServiceResponse;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
type Config = ();
|
||||
type Service = RouteService;
|
||||
type InitError = ();
|
||||
type Future = CreateRouteService;
|
||||
|
||||
fn new_service(&self, _: ()) -> Self::Future {
|
||||
CreateRouteService {
|
||||
fut: self.service.new_service(()),
|
||||
guards: self.guards.clone(),
|
||||
guards: self.guards.iter().map(|g| g.clone_guard()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CreateRouteService {
|
||||
fut: LocalBoxFuture<'static, Result<BoxedRouteService, ()>>,
|
||||
guards: Rc<Vec<Box<dyn Guard>>>,
|
||||
guards: Vec<Box<dyn Guard>>,
|
||||
}
|
||||
|
||||
impl Future for CreateRouteService {
|
||||
|
@ -93,7 +92,7 @@ impl Future for CreateRouteService {
|
|||
match this.fut.as_mut().poll(cx)? {
|
||||
Poll::Ready(service) => Poll::Ready(Ok(RouteService {
|
||||
service,
|
||||
guards: this.guards.clone(),
|
||||
guards: std::mem::take(&mut this.guards),
|
||||
})),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
|
@ -102,7 +101,7 @@ impl Future for CreateRouteService {
|
|||
|
||||
pub struct RouteService {
|
||||
service: BoxedRouteService,
|
||||
guards: Rc<Vec<Box<dyn Guard>>>,
|
||||
guards: Vec<Box<dyn Guard>>,
|
||||
}
|
||||
|
||||
impl RouteService {
|
||||
|
@ -145,9 +144,7 @@ impl Route {
|
|||
/// # }
|
||||
/// ```
|
||||
pub fn method(mut self, method: Method) -> Self {
|
||||
Rc::get_mut(&mut self.guards)
|
||||
.unwrap()
|
||||
.push(Box::new(guard::Method(method)));
|
||||
self.guards.push(Box::new(guard::Method(method)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -165,7 +162,7 @@ impl Route {
|
|||
/// # }
|
||||
/// ```
|
||||
pub fn guard<F: Guard + 'static>(mut self, f: F) -> Self {
|
||||
Rc::get_mut(&mut self.guards).unwrap().push(Box::new(f));
|
||||
self.guards.push(Box::new(f));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue