mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 09:42:40 +01:00
add application filters
This commit is contained in:
parent
789af0bbf2
commit
f7bd6eeedc
@ -22,6 +22,7 @@ pub struct HttpApplication<S = ()> {
|
|||||||
prefix_len: usize,
|
prefix_len: usize,
|
||||||
router: Router,
|
router: Router,
|
||||||
inner: Rc<UnsafeCell<Inner<S>>>,
|
inner: Rc<UnsafeCell<Inner<S>>>,
|
||||||
|
filters: Option<Vec<Box<Predicate<S>>>>,
|
||||||
middlewares: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
middlewares: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,11 +144,21 @@ impl<S: 'static> HttpHandler for HttpApplication<S> {
|
|||||||
|| path.split_at(self.prefix_len).1.starts_with('/'))
|
|| path.split_at(self.prefix_len).1.starts_with('/'))
|
||||||
};
|
};
|
||||||
if m {
|
if m {
|
||||||
let mut req = req.with_state(Rc::clone(&self.state), self.router.clone());
|
let mut req2 =
|
||||||
let tp = self.get_handler(&mut req);
|
req.clone_with_state(Rc::clone(&self.state), self.router.clone());
|
||||||
|
|
||||||
|
if let Some(ref filters) = self.filters {
|
||||||
|
for filter in filters {
|
||||||
|
if !filter.check(&mut req2) {
|
||||||
|
return Err(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tp = self.get_handler(&mut req2);
|
||||||
let inner = Rc::clone(&self.inner);
|
let inner = Rc::clone(&self.inner);
|
||||||
Ok(Box::new(Pipeline::new(
|
Ok(Box::new(Pipeline::new(
|
||||||
req,
|
req2,
|
||||||
Rc::clone(&self.middlewares),
|
Rc::clone(&self.middlewares),
|
||||||
inner,
|
inner,
|
||||||
tp,
|
tp,
|
||||||
@ -168,6 +179,7 @@ struct ApplicationParts<S> {
|
|||||||
external: HashMap<String, Resource>,
|
external: HashMap<String, Resource>,
|
||||||
encoding: ContentEncoding,
|
encoding: ContentEncoding,
|
||||||
middlewares: Vec<Box<Middleware<S>>>,
|
middlewares: Vec<Box<Middleware<S>>>,
|
||||||
|
filters: Vec<Box<Predicate<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Structure that follows the builder pattern for building application
|
/// Structure that follows the builder pattern for building application
|
||||||
@ -190,6 +202,7 @@ impl App<()> {
|
|||||||
handlers: Vec::new(),
|
handlers: Vec::new(),
|
||||||
external: HashMap::new(),
|
external: HashMap::new(),
|
||||||
encoding: ContentEncoding::Auto,
|
encoding: ContentEncoding::Auto,
|
||||||
|
filters: Vec::new(),
|
||||||
middlewares: Vec::new(),
|
middlewares: Vec::new(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@ -229,6 +242,7 @@ where
|
|||||||
handlers: Vec::new(),
|
handlers: Vec::new(),
|
||||||
external: HashMap::new(),
|
external: HashMap::new(),
|
||||||
middlewares: Vec::new(),
|
middlewares: Vec::new(),
|
||||||
|
filters: Vec::new(),
|
||||||
encoding: ContentEncoding::Auto,
|
encoding: ContentEncoding::Auto,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@ -285,6 +299,26 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add match predicate to application.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// # use actix_web::*;
|
||||||
|
/// # fn main() {
|
||||||
|
/// App::new()
|
||||||
|
/// .filter(pred::Get())
|
||||||
|
/// .resource("/path", |r| r.f(|_| HttpResponse::Ok()))
|
||||||
|
/// # .finish();
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn filter<T: Predicate<S> + 'static>(mut self, p: T) -> App<S> {
|
||||||
|
{
|
||||||
|
let parts = self.parts.as_mut().expect("Use after finish");
|
||||||
|
parts.filters.push(Box::new(p));
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Configure route for a specific path.
|
/// Configure route for a specific path.
|
||||||
///
|
///
|
||||||
/// This is a simplified version of the `App::resource()` method.
|
/// This is a simplified version of the `App::resource()` method.
|
||||||
@ -608,6 +642,11 @@ where
|
|||||||
handlers: parts.handlers,
|
handlers: parts.handlers,
|
||||||
resources,
|
resources,
|
||||||
}));
|
}));
|
||||||
|
let filters = if parts.filters.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(parts.filters)
|
||||||
|
};
|
||||||
|
|
||||||
HttpApplication {
|
HttpApplication {
|
||||||
state: Rc::new(parts.state),
|
state: Rc::new(parts.state),
|
||||||
@ -616,6 +655,7 @@ where
|
|||||||
prefix,
|
prefix,
|
||||||
prefix_len,
|
prefix_len,
|
||||||
inner,
|
inner,
|
||||||
|
filters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +740,8 @@ mod tests {
|
|||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
use test::TestRequest;
|
use pred;
|
||||||
|
use test::{TestRequest, TestServer};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_resource() {
|
fn test_default_resource() {
|
||||||
@ -899,4 +940,21 @@ mod tests {
|
|||||||
let resp = app.run(req);
|
let resp = app.run(req);
|
||||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_filter() {
|
||||||
|
let mut srv = TestServer::with_factory(|| {
|
||||||
|
App::new()
|
||||||
|
.filter(pred::Get())
|
||||||
|
.handler("/test", |_| HttpResponse::Ok())
|
||||||
|
});
|
||||||
|
|
||||||
|
let request = srv.get().uri(srv.url("/test")).finish().unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let request = srv.post().uri(srv.url("/test")).finish().unwrap();
|
||||||
|
let response = srv.execute(request.send()).unwrap();
|
||||||
|
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,12 @@ impl HttpRequest<()> {
|
|||||||
pub fn with_state<S>(self, state: Rc<S>, router: Router) -> HttpRequest<S> {
|
pub fn with_state<S>(self, state: Rc<S>, router: Router) -> HttpRequest<S> {
|
||||||
HttpRequest(self.0, Some(state), Some(router))
|
HttpRequest(self.0, Some(state), Some(router))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn clone_with_state<S>(
|
||||||
|
&self, state: Rc<S>, router: Router,
|
||||||
|
) -> HttpRequest<S> {
|
||||||
|
HttpRequest(self.0.clone(), Some(state), Some(router))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> HttpMessage for HttpRequest<S> {
|
impl<S> HttpMessage for HttpRequest<S> {
|
||||||
|
Loading…
Reference in New Issue
Block a user