add a Proxy type
Proxies can currently be configured to intercept HTTP, HTTPS, and all requests. HTTPS tunneling is supported. Closes #30
This commit is contained in:
@@ -14,8 +14,10 @@ use tokio_core::reactor::Handle;
|
||||
use super::body;
|
||||
use super::request::{self, Request, RequestBuilder};
|
||||
use super::response::{self, Response};
|
||||
use connect::Connector;
|
||||
use into_url::to_uri;
|
||||
use redirect::{self, RedirectPolicy, check_redirect, remove_sensitive_headers};
|
||||
use {Certificate, IntoUrl, Method, StatusCode, Url};
|
||||
use {Certificate, IntoUrl, Method, proxy, Proxy, StatusCode, Url};
|
||||
|
||||
static DEFAULT_USER_AGENT: &'static str =
|
||||
concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
|
||||
@@ -79,6 +81,7 @@ pub struct ClientBuilder {
|
||||
struct Config {
|
||||
gzip: bool,
|
||||
hostname_verification: bool,
|
||||
proxies: Vec<Proxy>,
|
||||
redirect_policy: RedirectPolicy,
|
||||
referer: bool,
|
||||
timeout: Option<Duration>,
|
||||
@@ -97,6 +100,7 @@ impl ClientBuilder {
|
||||
config: Some(Config {
|
||||
gzip: true,
|
||||
hostname_verification: true,
|
||||
proxies: Vec::new(),
|
||||
redirect_policy: RedirectPolicy::default(),
|
||||
referer: true,
|
||||
timeout: None,
|
||||
@@ -127,7 +131,9 @@ impl ClientBuilder {
|
||||
}
|
||||
*/
|
||||
|
||||
let hyper_client = create_hyper_client(tls, handle);
|
||||
let proxies = Arc::new(config.proxies);
|
||||
|
||||
let hyper_client = create_hyper_client(tls, proxies.clone(), handle);
|
||||
//let mut hyper_client = create_hyper_client(tls_client);
|
||||
|
||||
//hyper_client.set_read_timeout(config.timeout);
|
||||
@@ -137,6 +143,7 @@ impl ClientBuilder {
|
||||
inner: Arc::new(ClientRef {
|
||||
gzip: config.gzip,
|
||||
hyper: hyper_client,
|
||||
proxies: proxies,
|
||||
redirect_policy: config.redirect_policy,
|
||||
referer: config.referer,
|
||||
}),
|
||||
@@ -187,6 +194,13 @@ impl ClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a `Proxy` to the list of proxies the `Client` will use.
|
||||
#[inline]
|
||||
pub fn proxy(&mut self, proxy: Proxy) -> &mut ClientBuilder {
|
||||
self.config_mut().proxies.push(proxy);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a `RedirectPolicy` for this client.
|
||||
///
|
||||
/// Default will follow redirects up to a maximum of 10.
|
||||
@@ -226,14 +240,11 @@ impl ClientBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
type HyperClient = ::hyper::Client<::hyper_tls::HttpsConnector<::hyper::client::HttpConnector>>;
|
||||
type HyperClient = ::hyper::Client<Connector>;
|
||||
|
||||
fn create_hyper_client(tls: TlsConnector, handle: &Handle) -> HyperClient {
|
||||
let mut http = ::hyper::client::HttpConnector::new(4, handle);
|
||||
http.enforce_http(false);
|
||||
let https = ::hyper_tls::HttpsConnector::from((http, tls));
|
||||
fn create_hyper_client(tls: TlsConnector, proxies: Arc<Vec<Proxy>>, handle: &Handle) -> HyperClient {
|
||||
::hyper::Client::configure()
|
||||
.connector(https)
|
||||
.connector(Connector::new(tls, proxies, handle))
|
||||
.build(handle)
|
||||
}
|
||||
|
||||
@@ -363,7 +374,8 @@ impl Client {
|
||||
headers.set(AcceptEncoding(vec![qitem(Encoding::Gzip)]));
|
||||
}
|
||||
|
||||
let mut req = ::hyper::Request::new(method.clone(), url_to_uri(&url));
|
||||
let uri = to_uri(&url);
|
||||
let mut req = ::hyper::Request::new(method.clone(), uri.clone());
|
||||
*req.headers_mut() = headers.clone();
|
||||
let body = body.and_then(|body| {
|
||||
let (resuable, body) = body::into_hyper(body);
|
||||
@@ -371,6 +383,10 @@ impl Client {
|
||||
resuable
|
||||
});
|
||||
|
||||
if proxy::is_proxied(&self.inner.proxies, &uri) {
|
||||
req.set_proxy(true);
|
||||
}
|
||||
|
||||
let in_flight = self.inner.hyper.request(req);
|
||||
|
||||
Pending {
|
||||
@@ -408,6 +424,7 @@ impl fmt::Debug for ClientBuilder {
|
||||
struct ClientRef {
|
||||
gzip: bool,
|
||||
hyper: HyperClient,
|
||||
proxies: Arc<Vec<Proxy>>,
|
||||
redirect_policy: RedirectPolicy,
|
||||
referer: bool,
|
||||
}
|
||||
@@ -473,14 +490,18 @@ impl Future for Pending {
|
||||
|
||||
remove_sensitive_headers(&mut self.headers, &self.url, &self.urls);
|
||||
debug!("redirecting to {:?} '{}'", self.method, self.url);
|
||||
let uri = to_uri(&self.url);
|
||||
let mut req = ::hyper::Request::new(
|
||||
self.method.clone(),
|
||||
url_to_uri(&self.url)
|
||||
uri.clone()
|
||||
);
|
||||
*req.headers_mut() = self.headers.clone();
|
||||
if let Some(ref body) = self.body {
|
||||
req.set_body(body.clone());
|
||||
}
|
||||
if proxy::is_proxied(&self.client.proxies, &uri) {
|
||||
req.set_proxy(true);
|
||||
}
|
||||
self.in_flight = self.client.hyper.request(req);
|
||||
continue;
|
||||
},
|
||||
@@ -525,10 +546,6 @@ fn make_referer(next: &Url, previous: &Url) -> Option<Referer> {
|
||||
Some(Referer::new(referer.into_string()))
|
||||
}
|
||||
|
||||
fn url_to_uri(url: &Url) -> ::hyper::Uri {
|
||||
url.as_str().parse().expect("a parsed Url should always be a valid Uri")
|
||||
}
|
||||
|
||||
// pub(crate)
|
||||
|
||||
pub fn take_builder(builder: &mut ClientBuilder) -> ClientBuilder {
|
||||
|
||||
Reference in New Issue
Block a user