1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-22 08:07:18 +00:00

Don't normalize URIs with no valid path (#2246)

This commit is contained in:
Thales 2021-06-05 13:19:45 -03:00 committed by GitHub
parent 0bb035cfa7
commit b1e841f168
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 38 deletions

View file

@ -10,12 +10,14 @@
* Update `language-tags` to `0.3`. * Update `language-tags` to `0.3`.
* `ServiceResponse::take_body`. [#2201] * `ServiceResponse::take_body`. [#2201]
* `ServiceResponse::map_body` closure receives and returns `B` instead of `ResponseBody<B>` types. [#2201] * `ServiceResponse::map_body` closure receives and returns `B` instead of `ResponseBody<B>` types. [#2201]
* `middleware::normalize` now will not try to normalize URIs with no valid path [#2246]
### Removed ### Removed
* `HttpResponse::take_body` and old `HttpResponse::into_body` method that casted body type. [#2201] * `HttpResponse::take_body` and old `HttpResponse::into_body` method that casted body type. [#2201]
[#2200]: https://github.com/actix/actix-web/pull/2200 [#2200]: https://github.com/actix/actix-web/pull/2200
[#2201]: https://github.com/actix/actix-web/pull/2201 [#2201]: https://github.com/actix/actix-web/pull/2201
[#2246]: https://github.com/actix/actix-web/pull/2246
## 4.0.0-beta.6 - 2021-04-17 ## 4.0.0-beta.6 - 2021-04-17

View file

@ -137,9 +137,13 @@ where
let original_path = head.uri.path(); let original_path = head.uri.path();
// Either adds a string to the end (duplicates will be removed anyways) or trims all slashes from the end // An empty path here means that the URI has no valid path. We skip normalization in this
// case, because adding a path can make the URI invalid
if !original_path.is_empty() {
// Either adds a string to the end (duplicates will be removed anyways) or trims all
// slashes from the end
let path = match self.trailing_slash_behavior { let path = match self.trailing_slash_behavior {
TrailingSlash::Always => original_path.to_string() + "/", TrailingSlash::Always => format!("{}/", original_path),
TrailingSlash::MergeOnly => original_path.to_string(), TrailingSlash::MergeOnly => original_path.to_string(),
TrailingSlash::Trim => original_path.trim_end_matches('/').to_string(), TrailingSlash::Trim => original_path.trim_end_matches('/').to_string(),
}; };
@ -147,8 +151,8 @@ where
// normalize multiple /'s to one / // normalize multiple /'s to one /
let path = self.merge_slash.replace_all(&path, "/"); let path = self.merge_slash.replace_all(&path, "/");
// Ensure root paths are still resolvable. If resulting path is blank after previous step // Ensure root paths are still resolvable. If resulting path is blank after previous
// it means the path was one or more slashes. Reduce to single slash. // step it means the path was one or more slashes. Reduce to single slash.
let path = if path.is_empty() { "/" } else { path.as_ref() }; let path = if path.is_empty() { "/" } else { path.as_ref() };
// Check whether the path has been changed // Check whether the path has been changed
@ -166,10 +170,9 @@ where
let mut parts = head.uri.clone().into_parts(); let mut parts = head.uri.clone().into_parts();
let query = parts.path_and_query.as_ref().and_then(|pq| pq.query()); let query = parts.path_and_query.as_ref().and_then(|pq| pq.query());
let path = if let Some(q) = query { let path = match query {
Bytes::from(format!("{}?{}", path, q)) Some(q) => Bytes::from(format!("{}?{}", path, q)),
} else { None => Bytes::copy_from_slice(path.as_bytes()),
Bytes::copy_from_slice(path.as_bytes())
}; };
parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap()); parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path).unwrap());
@ -177,13 +180,14 @@ where
req.match_info_mut().get_mut().update(&uri); req.match_info_mut().get_mut().update(&uri);
req.head_mut().uri = uri; req.head_mut().uri = uri;
} }
}
self.service.call(req) self.service.call(req)
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use actix_http::StatusCode;
use actix_service::IntoService; use actix_service::IntoService;
use super::*; use super::*;
@ -387,6 +391,22 @@ mod tests {
} }
} }
#[actix_rt::test]
async fn no_path() {
let app = init_service(
App::new()
.wrap(NormalizePath::default())
.service(web::resource("/").to(HttpResponse::Ok)),
)
.await;
// This URI will be interpreted as an authority form, i.e. there is no path nor scheme
// (https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3)
let req = TestRequest::with_uri("eh").to_request();
let res = call_service(&app, req).await;
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[actix_rt::test] #[actix_rt::test]
async fn test_in_place_normalization() { async fn test_in_place_normalization() {
let srv = |req: ServiceRequest| { let srv = |req: ServiceRequest| {