Repository: actix/actix-web
File: src/middleware/normalize.rs (Rust)

Code before:
            // 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
            //
            // 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 query = parts.path_and_query.as_ref().and_then(|pq| pq.query());

                let path = if let Some(q) = query {
                    Bytes::from(format!("{}?{}", path, q))
                } else {
                    Bytes::copy_from_slice(path.as_bytes())
                };
                parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap());

                let uri = Uri::from_parts(parts).unwrap();
                req.match_info_mut().get_mut().update(&uri);
                req.head_mut().uri = uri;
            }
        }
        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_http::StatusCode;
    use actix_service::IntoService;

    use super::*;
    use crate::{
        dev::ServiceRequest,
        guard::fn_guard,
        test::{call_service, init_service, TestRequest},
        web, App, HttpResponse,
    };


Review comment (suggestion):
```suggestion
                let path = match query {
                    Some(q) => Bytes::from(format!("{}?{}", path, q)),
                    None => Bytes::copy_from_slice(path.as_bytes())
                };
```

Code after:
            // 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
            //
            // 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 query = parts.path_and_query.as_ref().and_then(|pq| pq.query());

                let path = match query {
                    Some(q) => Bytes::from(format!("{}?{}", path, q)),
                    None => Bytes::copy_from_slice(path.as_bytes()),
                };
                parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap());

                let uri = Uri::from_parts(parts).unwrap();
                req.match_info_mut().get_mut().update(&uri);
                req.head_mut().uri = uri;
            }
        }
        self.service.call(req)
    }
}

#[cfg(test)]
mod tests {
    use actix_http::StatusCode;
    use actix_service::IntoService;

    use super::*;
    use crate::{
        dev::ServiceRequest,
        guard::fn_guard,
        test::{call_service, init_service, TestRequest},
        web, App, HttpResponse,
    };

    #[actix_rt::test]