1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

awc: correctly handle redirections that begins with // (#2840)

This commit is contained in:
liushuyu 2022-08-24 20:12:58 -06:00 committed by GitHub
parent ea764b1d57
commit c9f91796df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 0 deletions

View File

@ -4,6 +4,11 @@
### Changed ### Changed
- Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
### Fixed
- Fixed handling of redirection requests that begin with `//`. [#2840]
[#2840]: https://github.com/actix/actix-web/pull/2840
## 3.0.0 - 2022-03-07 ## 3.0.0 - 2022-03-07
### Dependencies ### Dependencies

View File

@ -257,6 +257,16 @@ fn build_next_uri(res: &ClientResponse, prev_uri: &Uri) -> Result<Uri, SendReque
.scheme(prev_uri.scheme().cloned().unwrap()) .scheme(prev_uri.scheme().cloned().unwrap())
.authority(prev_uri.authority().cloned().unwrap()); .authority(prev_uri.authority().cloned().unwrap());
// scheme-relative address
if location.as_bytes().starts_with(b"//") {
let scheme = prev_uri.scheme_str().unwrap();
let mut full_url: Vec<u8> = 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 // when scheme or authority is missing treat the location value as path and query
// recover error where location does not have leading slash // recover error where location does not have leading slash
let path = if location.as_bytes().starts_with(b"/") { let path = if location.as_bytes().starts_with(b"/") {
@ -588,6 +598,41 @@ mod tests {
assert_eq!(res.status().as_u16(), 200); 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] #[actix_rt::test]
async fn test_remove_sensitive_headers() { async fn test_remove_sensitive_headers() {
fn gen_headers() -> header::HeaderMap { fn gen_headers() -> header::HeaderMap {