From 9af07d66ae092a0efe90829951f22aa948bc761f Mon Sep 17 00:00:00 2001 From: Fabianstelmach Date: Wed, 17 Jun 2020 11:54:20 +0200 Subject: [PATCH 1/3] Fix NormalizePath trailing slash behavior (#1548) --- CHANGES.md | 4 ++++ src/middleware/normalize.rs | 31 ++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3b4b8dc0b..3c21c301d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,10 @@ * Fix actix_http::h1::dispatcher so it returns when HW_BUFFER_SIZE is reached. Should reduce peak memory consumption during large uploads. [#1550] +### Fixed + +* `NormalizePath` improved consistency when path needs slashes added _and_ removed. + ## [3.0.0-alpha.3] - 2020-05-21 ### Added diff --git a/src/middleware/normalize.rs b/src/middleware/normalize.rs index d23f03445..3d5d30c80 100644 --- a/src/middleware/normalize.rs +++ b/src/middleware/normalize.rs @@ -16,6 +16,7 @@ use crate::Error; /// Performs following: /// /// - Merges multiple slashes into one. +/// - Appends a trailing slash if one is not present. /// /// ```rust /// use actix_web::{web, http, middleware, App, HttpResponse}; @@ -75,14 +76,26 @@ where fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let head = req.head_mut(); + let original_path = head.uri.path(); + // always add trailing slash, might be an extra one - let path = head.uri.path().to_string() + "/"; - let original_len = path.len(); + let path = original_path.to_string() + "/"; // normalize multiple /'s to one / let path = self.merge_slash.replace_all(&path, "/"); - if original_len != path.len() { + // Check whether the path has been changed + // + // This check was previously implemented as string length comparison + // + // That approach fails when a trailing slash is added, + // and a duplicate slash is removed, + // since the length of the strings remains the same + // + // For example, the path "/v1//s" will be normalized to "/v1/s/" + // Both of the paths have the same length, + // so the change can not be deduced from the length comparison + if path != original_path { let mut parts = head.uri.clone().into_parts(); let pq = parts.path_and_query.as_ref().unwrap(); @@ -131,6 +144,10 @@ mod tests { let req3 = TestRequest::with_uri("//v1//////something").to_request(); let res3 = call_service(&mut app, req3).await; assert!(res3.status().is_success()); + + let req4 = TestRequest::with_uri("/v1//something").to_request(); + let res4 = call_service(&mut app, req4).await; + assert!(res4.status().is_success()); } #[actix_rt::test] @@ -156,6 +173,10 @@ mod tests { let req3 = TestRequest::with_uri("//v1///something").to_srv_request(); let res3 = normalize.call(req3).await.unwrap(); assert!(res3.status().is_success()); + + let req4 = TestRequest::with_uri("/v1//something").to_srv_request(); + let res4 = normalize.call(req4).await.unwrap(); + assert!(res4.status().is_success()); } #[actix_rt::test] @@ -178,11 +199,11 @@ mod tests { } #[actix_rt::test] - async fn should_normalize_nothing_notrail() { + async fn should_normalize_notrail() { const URI: &str = "/v1/something"; let srv = |req: ServiceRequest| { - assert_eq!(URI, req.path()); + assert_eq!(URI.to_string() + "/", req.path()); ok(req.into_response(HttpResponse::Ok().finish())) }; From 0ba73fc44c7771975f761c5e2704d95ac5b18b10 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 18 Jun 2020 11:23:36 +0100 Subject: [PATCH 2/3] exclude default -web features on -actors (#1562) --- actix-web-actors/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 8db7a35ef..746aca2d5 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -17,7 +17,7 @@ path = "src/lib.rs" [dependencies] actix = "0.10.0-alpha.2" -actix-web = "3.0.0-alpha.3" +actix-web = { version = "3.0.0-alpha.3", default-features = false } actix-http = "2.0.0-alpha.4" actix-codec = "0.2.0" bytes = "0.5.2" From dc74db1f2f6a0686410633531960807836bb38b6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 18 Jun 2020 15:45:30 +0100 Subject: [PATCH 3/3] re-export actix_rt::main macro (#1559) --- CHANGES.md | 4 ++++ Cargo.toml | 2 +- README.md | 3 +-- examples/basic.rs | 2 +- examples/client.rs | 2 +- examples/uds.rs | 2 +- src/lib.rs | 1 + 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3c21c301d..c2dd43973 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +* Re-export `actix_rt::main` as `actix_web::main`. + ### Changed * Fix actix_http::h1::dispatcher so it returns when HW_BUFFER_SIZE is reached. Should reduce peak memory consumption during large uploads. [#1550] diff --git a/Cargo.toml b/Cargo.toml index 8c6d461d6..ade432c6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ actix-codec = "0.2.0" actix-service = "1.0.2" actix-utils = "1.0.6" actix-router = "0.2.4" -actix-rt = "1.0.0" +actix-rt = "1.1.1" actix-server = "1.0.0" actix-testing = "1.0.0" actix-macros = "0.1.0" diff --git a/README.md b/README.md index 97e3ceeae..6382abd4d 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,6 @@ Dependencies: ```toml [dependencies] actix-web = "2" -actix-rt = "1" ``` Code: @@ -66,7 +65,7 @@ async fn index(info: web::Path<(u32, String)>) -> impl Responder { format!("Hello {}! id:{}", info.1, info.0) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().service(index)) .bind("127.0.0.1:8080")? diff --git a/examples/basic.rs b/examples/basic.rs index bd6f8146f..8b2bf2319 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -16,7 +16,7 @@ async fn no_params() -> &'static str { "Hello world!\r\n" } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); env_logger::init(); diff --git a/examples/client.rs b/examples/client.rs index 874e08e1b..15cf24fa8 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -1,6 +1,6 @@ use actix_http::Error; -#[actix_rt::main] +#[actix_web::main] async fn main() -> Result<(), Error> { std::env::set_var("RUST_LOG", "actix_http=trace"); env_logger::init(); diff --git a/examples/uds.rs b/examples/uds.rs index 06aa87f4d..e34fa5ac9 100644 --- a/examples/uds.rs +++ b/examples/uds.rs @@ -20,7 +20,7 @@ async fn no_params() -> &'static str { } #[cfg(unix)] -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); env_logger::init(); diff --git a/src/lib.rs b/src/lib.rs index cff4acf27..09642806f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,6 +112,7 @@ pub use actix_web_codegen::*; // re-export for convenience pub use actix_http::Response as HttpResponse; pub use actix_http::{body, cookie, http, Error, HttpMessage, ResponseError, Result}; +pub use actix_macros::{main, test as test_rt}; pub use crate::app::App; pub use crate::extract::FromRequest;