From a73d885db7ec27a28fc7445c51bf5632ee311241 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Sun, 14 Aug 2022 22:30:20 -0600 Subject: [PATCH] awc/middleware/redirect: correctly handle redirections... ... that begins with `//` --- awc/CHANGES.md | 2 ++ awc/src/middleware/redirect.rs | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index e229a6d96..26c69bde8 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -4,6 +4,8 @@ ### Changed - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. +### Fixed +- Fixed handling of redirection requests that begin with `//`. [#XXXX] ## 3.0.0 - 2022-03-07 ### Dependencies diff --git a/awc/src/middleware/redirect.rs b/awc/src/middleware/redirect.rs index d48822168..67ef5d76f 100644 --- a/awc/src/middleware/redirect.rs +++ b/awc/src/middleware/redirect.rs @@ -257,6 +257,16 @@ fn build_next_uri(res: &ClientResponse, prev_uri: &Uri) -> Result = scheme.as_bytes().to_vec(); + full_url.push(b':'); + full_url.extend(location.as_bytes()); + + return Uri::try_from(full_url) + .map_err(|_| SendRequestError::Url(InvalidUrl::MissingScheme)); + } // when scheme or authority is missing treat the location value as path and query // recover error where location does not have leading slash let path = if location.as_bytes().starts_with(b"/") { @@ -588,6 +598,41 @@ mod tests { assert_eq!(res.status().as_u16(), 200); } + #[actix_rt::test] + async fn test_double_slash_redirect() { + let client = ClientBuilder::new() + .disable_redirects() + .wrap(Redirect::new().max_redirect_times(10)) + .finish(); + + let srv = actix_test::start(|| { + App::new() + .service(web::resource("/test").route(web::to(|| async { + Ok::<_, Error>(HttpResponse::BadRequest()) + }))) + .service( + web::resource("/").route(web::to(|req: HttpRequest| async move { + Ok::<_, Error>( + HttpResponse::Found() + .append_header(( + "location", + format!( + "//localhost:{}/test", + req.app_config().local_addr().port() + ) + .as_str(), + )) + .finish(), + ) + })), + ) + }); + + let res = client.get(srv.url("/")).send().await.unwrap(); + + assert_eq!(res.status().as_u16(), 400); + } + #[actix_rt::test] async fn test_remove_sensitive_headers() { fn gen_headers() -> header::HeaderMap {