Skip to content

Commit 6334345

Browse files
authored
support url with authority (#735)
1 parent d2cbc8e commit 6334345

File tree

3 files changed

+85
-8
lines changed

3 files changed

+85
-8
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ matrix:
4646
script: cargo build --target "$TARGET" --no-default-features
4747

4848
# minimum version
49-
- rust: 1.34.0
49+
- rust: 1.36.0
5050
script: cargo build
5151

5252
sudo: false

src/async_impl/request.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,18 @@ impl Request {
9595

9696
impl RequestBuilder {
9797
pub(super) fn new(client: Client, request: ::Result<Request>) -> RequestBuilder {
98-
RequestBuilder {
99-
client,
100-
request,
98+
let mut builder = RequestBuilder { client, request };
99+
100+
let auth = builder
101+
.request
102+
.as_mut()
103+
.ok()
104+
.and_then(|req| extract_authority(&mut req.url));
105+
106+
if let Some((username, password)) = auth {
107+
builder.basic_auth(username, password)
108+
} else {
109+
builder
101110
}
102111
}
103112

@@ -170,7 +179,7 @@ impl RequestBuilder {
170179
Some(password) => format!("{}:{}", username, password),
171180
None => format!("{}:", username)
172181
};
173-
let header_value = format!("Basic {}", encode(&auth));
182+
let header_value = format!("Basic {}", encode(&dbg!(auth)));
174183
self.header(::header::AUTHORIZATION, &*header_value)
175184
}
176185

@@ -424,6 +433,37 @@ pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) {
424433
}
425434
}
426435

436+
437+
/// Check the request URL for a "username:password" type authority, and if
438+
/// found, remove it from the URL and return it.
439+
pub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>)> {
440+
use url::percent_encoding::percent_decode;
441+
442+
if url.has_authority() {
443+
let username: String = percent_decode(url.username().as_bytes())
444+
.decode_utf8()
445+
.ok()?
446+
.into();
447+
let password = url.password().and_then(|pass| {
448+
percent_decode(pass.as_bytes())
449+
.decode_utf8()
450+
.ok()
451+
.map(String::from)
452+
});
453+
if !username.is_empty() || password.is_some() {
454+
url
455+
.set_username("")
456+
.expect("has_authority means set_username shouldn't fail");
457+
url
458+
.set_password(None)
459+
.expect("has_authority means set_password shouldn't fail");
460+
return Some((username, password))
461+
}
462+
}
463+
464+
None
465+
}
466+
427467
#[cfg(test)]
428468
mod tests {
429469
use super::Client;
@@ -536,6 +576,20 @@ mod tests {
536576
assert_eq!(req.url().as_str(), "https://google.com/");
537577
}
538578

579+
#[test]
580+
fn convert_url_authority_into_basic_auth() {
581+
let client = Client::new();
582+
let some_url = "https://Aladdin:open sesame@localhost/";
583+
584+
let req = client
585+
.get(some_url)
586+
.build()
587+
.expect("request build");
588+
589+
assert_eq!(req.url().as_str(), "https://localhost/");
590+
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
591+
}
592+
539593
/*
540594
use {body, Method};
541595
use super::Client;

src/request.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,18 @@ impl Request {
119119

120120
impl RequestBuilder {
121121
pub(crate) fn new(client: Client, request: ::Result<Request>) -> RequestBuilder {
122-
RequestBuilder {
123-
client,
124-
request,
122+
let mut builder = RequestBuilder { client, request };
123+
124+
let auth = builder
125+
.request
126+
.as_mut()
127+
.ok()
128+
.and_then(|req| async_impl::request::extract_authority(req.url_mut()));
129+
130+
if let Some((username, password)) = auth {
131+
builder.basic_auth(username, password)
132+
} else {
133+
builder
125134
}
126135
}
127136

@@ -883,4 +892,18 @@ mod tests {
883892
assert_eq!(req.url().query(), None);
884893
assert_eq!(req.url().as_str(), "https://google.com/");
885894
}
895+
896+
#[test]
897+
fn convert_url_authority_into_basic_auth() {
898+
let client = Client::new();
899+
let some_url = "https://Aladdin:open sesame@localhost/";
900+
901+
let req = client
902+
.get(some_url)
903+
.build()
904+
.expect("request build");
905+
906+
assert_eq!(req.url().as_str(), "https://localhost/");
907+
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
908+
}
886909
}

0 commit comments

Comments
 (0)