Fix NormalizePath trailing slash appending

NormalizePath would append a trailing slash if and only if it would
merge multiple slashes into one. For example, the following path would
not get a trailing slash appended:

"/sample/path"

On the other hand, this path would get a trailing slash appended:

"/sample//path"

After this commit, the trailing slash is appended for both the paths.
This commit is contained in:
Fabian Stelmach 2020-05-31 22:35:57 +02:00
parent 4f9a1ac3b7
commit bebd1166e8
1 changed files with 17 additions and 5 deletions

View File

@ -75,14 +75,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();
@ -178,11 +190,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()))
};