Skip to content

Commit

Permalink
support url with authority (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmonstar committed Dec 11, 2019
1 parent 7631c03 commit 518d3c0
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
59 changes: 58 additions & 1 deletion src/async_impl/request.rs
Expand Up @@ -112,7 +112,19 @@ impl Request {

impl 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.
Expand Down Expand Up @@ -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)]
mod tests {
use super::Client;
Expand Down Expand Up @@ -588,6 +631,20 @@ mod tests {
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 super::Client;
Expand Down
28 changes: 27 additions & 1 deletion src/blocking/request.rs
Expand Up @@ -122,7 +122,19 @@ impl Request {

impl 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.
Expand Down Expand Up @@ -872,4 +884,18 @@ mod tests {
assert_eq!(req.url().query(), None);
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==");
}
}

0 comments on commit 518d3c0

Please sign in to comment.