mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
Merge pull request #339 from joshleeb/propogate-scope-default-resource
Propagate scope default resource
This commit is contained in:
commit
5a9992736f
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
* `HttpRequest::url_for_static()` for a named route with no variables segments
|
* `HttpRequest::url_for_static()` for a named route with no variables segments
|
||||||
|
|
||||||
|
* Propagation of the application's default resource to scopes that haven't set a default resource.
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub struct HttpApplication<S = ()> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct Inner<S> {
|
pub struct Inner<S> {
|
||||||
prefix: usize,
|
prefix: usize,
|
||||||
default: ResourceHandler<S>,
|
default: Rc<RefCell<ResourceHandler<S>>>,
|
||||||
encoding: ContentEncoding,
|
encoding: ContentEncoding,
|
||||||
resources: Vec<ResourceHandler<S>>,
|
resources: Vec<ResourceHandler<S>>,
|
||||||
handlers: Vec<PrefixHandlerType<S>>,
|
handlers: Vec<PrefixHandlerType<S>>,
|
||||||
@ -51,7 +51,7 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
|||||||
match htype {
|
match htype {
|
||||||
HandlerType::Normal(idx) => match self.resources[idx].handle(req) {
|
HandlerType::Normal(idx) => match self.resources[idx].handle(req) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(req) => match self.default.handle(req) {
|
Err(req) => match self.default.borrow_mut().handle(req) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
|
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
|
||||||
},
|
},
|
||||||
@ -60,7 +60,7 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
|||||||
PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req),
|
PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req),
|
||||||
PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req),
|
PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req),
|
||||||
},
|
},
|
||||||
HandlerType::Default => match self.default.handle(req) {
|
HandlerType::Default => match self.default.borrow_mut().handle(req) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
|
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
|
||||||
},
|
},
|
||||||
@ -172,7 +172,7 @@ struct ApplicationParts<S> {
|
|||||||
state: S,
|
state: S,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
settings: ServerSettings,
|
settings: ServerSettings,
|
||||||
default: ResourceHandler<S>,
|
default: Rc<RefCell<ResourceHandler<S>>>,
|
||||||
resources: Vec<(Resource, Option<ResourceHandler<S>>)>,
|
resources: Vec<(Resource, Option<ResourceHandler<S>>)>,
|
||||||
handlers: Vec<PrefixHandlerType<S>>,
|
handlers: Vec<PrefixHandlerType<S>>,
|
||||||
external: HashMap<String, Resource>,
|
external: HashMap<String, Resource>,
|
||||||
@ -223,7 +223,7 @@ where
|
|||||||
state,
|
state,
|
||||||
prefix: "/".to_owned(),
|
prefix: "/".to_owned(),
|
||||||
settings: ServerSettings::default(),
|
settings: ServerSettings::default(),
|
||||||
default: ResourceHandler::default_not_found(),
|
default: Rc::new(RefCell::new(ResourceHandler::default_not_found())),
|
||||||
resources: Vec::new(),
|
resources: Vec::new(),
|
||||||
handlers: Vec::new(),
|
handlers: Vec::new(),
|
||||||
external: HashMap::new(),
|
external: HashMap::new(),
|
||||||
@ -474,7 +474,7 @@ where
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
let parts = self.parts.as_mut().expect("Use after finish");
|
let parts = self.parts.as_mut().expect("Use after finish");
|
||||||
f(&mut parts.default);
|
f(&mut parts.default.borrow_mut());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -615,7 +615,7 @@ where
|
|||||||
|
|
||||||
/// Finish application configuration and create `HttpHandler` object.
|
/// Finish application configuration and create `HttpHandler` object.
|
||||||
pub fn finish(&mut self) -> HttpApplication<S> {
|
pub fn finish(&mut self) -> HttpApplication<S> {
|
||||||
let parts = self.parts.take().expect("Use after finish");
|
let mut parts = self.parts.take().expect("Use after finish");
|
||||||
let prefix = parts.prefix.trim().trim_right_matches('/');
|
let prefix = parts.prefix.trim().trim_right_matches('/');
|
||||||
let (prefix, prefix_len) = if prefix.is_empty() {
|
let (prefix, prefix_len) = if prefix.is_empty() {
|
||||||
("/".to_owned(), 0)
|
("/".to_owned(), 0)
|
||||||
@ -628,11 +628,19 @@ where
|
|||||||
resources.push((pattern, None));
|
resources.push((pattern, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ref mut handler in parts.handlers.iter_mut() {
|
||||||
|
if let PrefixHandlerType::Scope(_, ref mut route_handler, _) = handler {
|
||||||
|
if !route_handler.has_default_resource() {
|
||||||
|
route_handler.default_resource(Rc::clone(&parts.default));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let (router, resources) = Router::new(&prefix, parts.settings, resources);
|
let (router, resources) = Router::new(&prefix, parts.settings, resources);
|
||||||
|
|
||||||
let inner = Rc::new(RefCell::new(Inner {
|
let inner = Rc::new(RefCell::new(Inner {
|
||||||
prefix: prefix_len,
|
prefix: prefix_len,
|
||||||
default: parts.default,
|
default: Rc::clone(&parts.default),
|
||||||
encoding: parts.encoding,
|
encoding: parts.encoding,
|
||||||
handlers: parts.handlers,
|
handlers: parts.handlers,
|
||||||
resources,
|
resources,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use futures::future::{err, ok, Future};
|
use futures::future::{err, ok, Future};
|
||||||
use futures::{Async, Poll};
|
use futures::{Async, Poll};
|
||||||
@ -8,6 +10,7 @@ use error::Error;
|
|||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
|
use resource::ResourceHandler;
|
||||||
|
|
||||||
/// Trait defines object that could be registered as route handler
|
/// Trait defines object that could be registered as route handler
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -403,6 +406,14 @@ where
|
|||||||
// /// Trait defines object that could be registered as resource route
|
// /// Trait defines object that could be registered as resource route
|
||||||
pub(crate) trait RouteHandler<S>: 'static {
|
pub(crate) trait RouteHandler<S>: 'static {
|
||||||
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>;
|
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>;
|
||||||
|
|
||||||
|
fn has_default_resource(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_resource(&mut self, default: Rc<RefCell<ResourceHandler<S>>>) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Route handler wrapper for Handler
|
/// Route handler wrapper for Handler
|
||||||
|
31
src/scope.rs
31
src/scope.rs
@ -405,6 +405,14 @@ impl<S: 'static> RouteHandler<S> for Scope<S> {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_default_resource(&self) -> bool {
|
||||||
|
self.default.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_resource(&mut self, default: ScopeResource<S>) {
|
||||||
|
self.default = Some(default);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Wrapper<S: 'static> {
|
struct Wrapper<S: 'static> {
|
||||||
@ -1188,4 +1196,27 @@ 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_default_resource_propagation() {
|
||||||
|
let mut app = App::new()
|
||||||
|
.scope("/app1", |scope| {
|
||||||
|
scope.default_resource(|r| r.f(|_| HttpResponse::BadRequest()))
|
||||||
|
})
|
||||||
|
.scope("/app2", |scope| scope)
|
||||||
|
.default_resource(|r| r.f(|_| HttpResponse::MethodNotAllowed()))
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/non-exist").finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app1/non-exist").finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/app2/non-exist").finish();
|
||||||
|
let resp = app.run(req);
|
||||||
|
assert_eq!(resp.as_msg().status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user