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