diff --git a/CHANGES.md b/CHANGES.md index f371eb286..0e663644e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # Changes +* Fix scope resource path extractor #234 + + ## 0.6.7 (2018-05-17) * Fix compilation with --no-default-features diff --git a/src/param.rs b/src/param.rs index 386c0c338..119ad59c3 100644 --- a/src/param.rs +++ b/src/param.rs @@ -58,6 +58,16 @@ impl<'a> Params<'a> { self.0.push((name, value)); } + pub(crate) fn remove(&mut self, name: &str) + { + for idx in (0..self.0.len()).rev() { + if self.0[idx].0 == name { + self.0.remove(idx); + return + } + } + } + /// Check if there are any matched patterns pub fn is_empty(&self) -> bool { self.0.is_empty() diff --git a/src/scope.rs b/src/scope.rs index 7cf9c6463..edbf81df0 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -336,6 +336,7 @@ impl RouteHandler for Scope { if pattern.match_with_params(path, req.match_info_mut()) { let default = unsafe { &mut *self.default.as_ref().get() }; + req.match_info_mut().remove("tail"); if self.middlewares.is_empty() { let resource = unsafe { &mut *resource.get() }; return resource.handle(req, Some(default)); diff --git a/tests/test_handlers.rs b/tests/test_handlers.rs index 11565fd37..cc6524d41 100644 --- a/tests/test_handlers.rs +++ b/tests/test_handlers.rs @@ -368,6 +368,80 @@ fn test_path_and_query_extractor2_async4() { assert_eq!(response.status(), StatusCode::BAD_REQUEST); } +#[test] +fn test_scope_and_path_extractor() { + let mut srv = test::TestServer::with_factory(move || { + App::new().scope("/sc", |scope| { + scope.resource("/{num}/index.html", |r| { + r.route() + .with(|p: Path<(usize,)>| { + format!("Welcome {}!", p.0) + }) + }) + }) + }); + + // client request + let request = srv + .get() + .uri(srv.url("/sc/10/index.html")) + .finish() + .unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = srv.execute(response.body()).unwrap(); + assert_eq!(bytes, Bytes::from_static(b"Welcome 10!")); + + // client request + let request = srv + .get() + .uri(srv.url("/sc/test1/index.html")) + .finish() + .unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert_eq!(response.status(), StatusCode::NOT_FOUND); +} + +#[test] +fn test_nested_scope_and_path_extractor() { + let mut srv = test::TestServer::with_factory(move || { + App::new().scope("/sc", |scope| { + scope.nested("/{num}", |scope| { + scope.resource("/{num}/index.html", |r| { + r.route() + .with(|p: Path<(usize, usize)>| { + format!("Welcome {} {}!", p.0, p.1) + }) + }) + }) + }) + }); + + // client request + let request = srv + .get() + .uri(srv.url("/sc/10/12/index.html")) + .finish() + .unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = srv.execute(response.body()).unwrap(); + assert_eq!(bytes, Bytes::from_static(b"Welcome 10 12!")); + + // client request + let request = srv + .get() + .uri(srv.url("/sc/10/test1/index.html")) + .finish() + .unwrap(); + let response = srv.execute(request.send()).unwrap(); + assert_eq!(response.status(), StatusCode::NOT_FOUND); +} + #[cfg(actix_impl_trait)] fn test_impl_trait( data: (Json, Path, Query),