support url with authority (#736)

This commit is contained in:
Sean McArthur
2019-12-11 13:42:45 -08:00
committed by GitHub
parent 7631c0390e
commit be52c4d558
2 changed files with 85 additions and 2 deletions

View File

@@ -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;

View File

@@ -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==");
}
} }