diff --git a/CHANGES.md b/CHANGES.md index aadf627bc..15d3c81ce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,13 @@ ## Unreleased - 2020-xx-xx +## 3.0.2 - 2020-09-15 +### Fixed +* `NormalizePath` when used with `TrailingSlash::Trim` no longer trims the root path "/". [#1678] + +[#1678]: https://github.com/actix/actix-web/pull/1678 + + ## 3.0.1 - 2020-09-13 ### Changed * `middleware::normalize::TrailingSlash` enum is now accessible. [#1673] diff --git a/Cargo.toml b/Cargo.toml index b2cffbc48..8ce615433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "3.0.1" +version = "3.0.2" authors = ["Nikolay Kim "] description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust." readme = "README.md" diff --git a/src/middleware/normalize.rs b/src/middleware/normalize.rs index 1b6894796..8452c9083 100644 --- a/src/middleware/normalize.rs +++ b/src/middleware/normalize.rs @@ -79,6 +79,7 @@ where } } +#[doc(hidden)] pub struct NormalizePathNormalization { service: S, merge_slash: Regex, @@ -113,6 +114,10 @@ where // normalize multiple /'s to one / let path = self.merge_slash.replace_all(&path, "/"); + // Ensure root paths are still resolvable. If resulting path is blank after previous step + // it means the path was one or more slashes. Reduce to single slash. + let path = if path.is_empty() { "/" } else { path.as_ref() }; + // Check whether the path has been changed // // This check was previously implemented as string length comparison @@ -158,10 +163,23 @@ mod tests { let mut app = init_service( App::new() .wrap(NormalizePath::default()) + .service(web::resource("/").to(HttpResponse::Ok)) .service(web::resource("/v1/something/").to(HttpResponse::Ok)), ) .await; + let req = TestRequest::with_uri("/").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + + let req = TestRequest::with_uri("/?query=test").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + + let req = TestRequest::with_uri("///").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + let req = TestRequest::with_uri("/v1//something////").to_request(); let res = call_service(&mut app, req).await; assert!(res.status().is_success()); @@ -184,10 +202,24 @@ mod tests { let mut app = init_service( App::new() .wrap(NormalizePath(TrailingSlash::Trim)) + .service(web::resource("/").to(HttpResponse::Ok)) .service(web::resource("/v1/something").to(HttpResponse::Ok)), ) .await; + // root paths should still work + let req = TestRequest::with_uri("/").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + + let req = TestRequest::with_uri("/?query=test").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + + let req = TestRequest::with_uri("///").to_request(); + let res = call_service(&mut app, req).await; + assert!(res.status().is_success()); + let req = TestRequest::with_uri("/v1/something////").to_request(); let res = call_service(&mut app, req).await; assert!(res.status().is_success()); diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index e71e9d0b8..0a11e2cae 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -2,11 +2,13 @@ ## Unreleased - 2020-xx-xx +* add ability to set address for `TestServer` [#1645] + +[#1645]: https://github.com/actix/actix-web/pull/1645 ## 2.0.0 - 2020-09-11 * Update actix-codec and actix-utils dependencies. - ## 2.0.0-alpha.1 - 2020-05-23 * Update the `time` dependency to 0.2.7 * Update `actix-connect` dependency to 2.0.0-alpha.2 diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 5d5750279..4159c8d86 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -44,12 +44,20 @@ pub use actix_testing::*; /// } /// ``` pub async fn test_server>(factory: F) -> TestServer { + let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap(); + test_server_with_addr(tcp, factory).await +} + +/// Start [`test server`](./fn.test_server.html) on a concrete Address +pub async fn test_server_with_addr>( + tcp: net::TcpListener, + factory: F, +) -> TestServer { let (tx, rx) = mpsc::channel(); // run server in separate thread thread::spawn(move || { let sys = System::new("actix-test-server"); - let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap(); let local_addr = tcp.local_addr().unwrap(); Server::build()