support url with authority (#736)
This commit is contained in:
		| @@ -112,7 +112,19 @@ impl Request { | |||||||
|  |  | ||||||
| impl RequestBuilder { | impl RequestBuilder { | ||||||
|     pub(super) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder { |     pub(super) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder { | ||||||
|         RequestBuilder { client, request } |         let mut builder = RequestBuilder { client, request }; | ||||||
|  |  | ||||||
|  |         let auth = builder | ||||||
|  |             .request | ||||||
|  |             .as_mut() | ||||||
|  |             .ok() | ||||||
|  |             .and_then(|req| extract_authority(&mut req.url)); | ||||||
|  |  | ||||||
|  |         if let Some((username, password)) = auth { | ||||||
|  |             builder.basic_auth(username, password) | ||||||
|  |         } else { | ||||||
|  |             builder | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Add a `Header` to this Request. |     /// Add a `Header` to this Request. | ||||||
| @@ -430,6 +442,37 @@ pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// Check the request URL for a "username:password" type authority, and if | ||||||
|  | /// found, remove it from the URL and return it. | ||||||
|  | pub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>)> { | ||||||
|  |     use percent_encoding::percent_decode; | ||||||
|  |  | ||||||
|  |     if url.has_authority() { | ||||||
|  |         let username: String = percent_decode(url.username().as_bytes()) | ||||||
|  |             .decode_utf8() | ||||||
|  |             .ok()? | ||||||
|  |             .into(); | ||||||
|  |         let password = url.password().and_then(|pass| { | ||||||
|  |             percent_decode(pass.as_bytes()) | ||||||
|  |                 .decode_utf8() | ||||||
|  |                 .ok() | ||||||
|  |                 .map(String::from) | ||||||
|  |         }); | ||||||
|  |         if !username.is_empty() || password.is_some() { | ||||||
|  |             url | ||||||
|  |                 .set_username("") | ||||||
|  |                 .expect("has_authority means set_username shouldn't fail"); | ||||||
|  |             url | ||||||
|  |                 .set_password(None) | ||||||
|  |                 .expect("has_authority means set_password shouldn't fail"); | ||||||
|  |             return Some((username, password)) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     None | ||||||
|  | } | ||||||
|  |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use super::Client; |     use super::Client; | ||||||
| @@ -588,6 +631,20 @@ mod tests { | |||||||
|         assert!(clone.is_none()); |         assert!(clone.is_none()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn convert_url_authority_into_basic_auth() { | ||||||
|  |         let client = Client::new(); | ||||||
|  |         let some_url = "https://Aladdin:open sesame@localhost/"; | ||||||
|  |  | ||||||
|  |         let req = client | ||||||
|  |             .get(some_url) | ||||||
|  |             .build() | ||||||
|  |             .expect("request build"); | ||||||
|  |  | ||||||
|  |         assert_eq!(req.url().as_str(), "https://localhost/"); | ||||||
|  |         assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|     use {body, Method}; |     use {body, Method}; | ||||||
|     use super::Client; |     use super::Client; | ||||||
|   | |||||||
| @@ -122,7 +122,19 @@ impl Request { | |||||||
|  |  | ||||||
| impl RequestBuilder { | impl RequestBuilder { | ||||||
|     pub(crate) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder { |     pub(crate) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder { | ||||||
|         RequestBuilder { client, request } |         let mut builder = RequestBuilder { client, request }; | ||||||
|  |  | ||||||
|  |         let auth = builder | ||||||
|  |             .request | ||||||
|  |             .as_mut() | ||||||
|  |             .ok() | ||||||
|  |             .and_then(|req| async_impl::request::extract_authority(req.url_mut())); | ||||||
|  |  | ||||||
|  |         if let Some((username, password)) = auth { | ||||||
|  |             builder.basic_auth(username, password) | ||||||
|  |         } else { | ||||||
|  |             builder | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Add a `Header` to this Request. |     /// Add a `Header` to this Request. | ||||||
| @@ -872,4 +884,18 @@ mod tests { | |||||||
|         assert_eq!(req.url().query(), None); |         assert_eq!(req.url().query(), None); | ||||||
|         assert_eq!(req.url().as_str(), "https://google.com/"); |         assert_eq!(req.url().as_str(), "https://google.com/"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn convert_url_authority_into_basic_auth() { | ||||||
|  |         let client = Client::new(); | ||||||
|  |         let some_url = "https://Aladdin:open sesame@localhost/"; | ||||||
|  |  | ||||||
|  |         let req = client | ||||||
|  |             .get(some_url) | ||||||
|  |             .build() | ||||||
|  |             .expect("request build"); | ||||||
|  |  | ||||||
|  |         assert_eq!(req.url().as_str(), "https://localhost/"); | ||||||
|  |         assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user