99
src/proxy.rs
99
src/proxy.rs
@@ -1,6 +1,7 @@
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use http::{header::HeaderValue, Uri};
|
||||
use hyper::client::connect::Destination;
|
||||
use {into_url, IntoUrl, Url};
|
||||
|
||||
@@ -30,9 +31,15 @@ use {into_url, IntoUrl, Url};
|
||||
/// would prevent a `Proxy` later in the list from ever working, so take care.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Proxy {
|
||||
auth: Option<Auth>,
|
||||
intercept: Intercept,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Auth {
|
||||
Basic(HeaderValue),
|
||||
}
|
||||
|
||||
impl Proxy {
|
||||
/// Proxy all HTTP traffic to the passed URL.
|
||||
///
|
||||
@@ -124,7 +131,43 @@ impl Proxy {
|
||||
|
||||
fn new(intercept: Intercept) -> Proxy {
|
||||
Proxy {
|
||||
intercept: intercept,
|
||||
auth: None,
|
||||
intercept,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the `Proxy-Authorization` header using Basic auth.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate reqwest;
|
||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||
/// let proxy = reqwest::Proxy::https("http://localhost:1234")?
|
||||
/// .basic_auth("Aladdin", "open sesame");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
pub fn basic_auth(mut self, username: &str, password: &str) -> Proxy {
|
||||
self.auth = Some(Auth::basic(username, password));
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn auth(&self) -> Option<&Auth> {
|
||||
self.auth.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_has_http_auth(&self) -> bool {
|
||||
match self.auth {
|
||||
Some(Auth::Basic(_)) => match self.intercept {
|
||||
Intercept::All(_) |
|
||||
Intercept::Http(_) |
|
||||
// Custom *may* match 'http', so assume so.
|
||||
Intercept::Custom(_) => true,
|
||||
Intercept::Https(_) => false,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +204,31 @@ impl Proxy {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_match<D: Dst>(&self, uri: &D) -> bool {
|
||||
match self.intercept {
|
||||
Intercept::All(_) => true,
|
||||
Intercept::Http(_) => {
|
||||
uri.scheme() == "http"
|
||||
},
|
||||
Intercept::Https(_) => {
|
||||
uri.scheme() == "https"
|
||||
},
|
||||
Intercept::Custom(ref fun) => {
|
||||
(fun.0)(
|
||||
&format!(
|
||||
"{}://{}{}{}",
|
||||
uri.scheme(),
|
||||
uri.host(),
|
||||
uri.port().map(|_| ":").unwrap_or(""),
|
||||
uri.port().map(|p| p.to_string()).unwrap_or(String::new())
|
||||
)
|
||||
.parse()
|
||||
.expect("should be valid Url")
|
||||
).is_some()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -203,6 +271,35 @@ impl Dst for Destination {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl Dst for Uri {
|
||||
fn scheme(&self) -> &str {
|
||||
self.scheme_part()
|
||||
.expect("Uri should have a scheme")
|
||||
.as_str()
|
||||
}
|
||||
|
||||
fn host(&self) -> &str {
|
||||
Uri::host(self)
|
||||
.expect("<Uri as Dst>::host should have a str")
|
||||
}
|
||||
|
||||
fn port(&self) -> Option<u16> {
|
||||
self.port_part().map(|p| p.as_u16())
|
||||
}
|
||||
}
|
||||
|
||||
impl Auth {
|
||||
pub(crate) fn basic(username: &str, password: &str) -> Auth {
|
||||
let val = format!("{}:{}", username, password);
|
||||
let mut header = format!("Basic {}", base64::encode(&val))
|
||||
.parse::<HeaderValue>()
|
||||
.expect("base64 is always valid HeaderValue");
|
||||
header.set_sensitive(true);
|
||||
Auth::Basic(header)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user