add custom certificates & disabling hostname verif
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							d12d604e38
						
					
				
				
					commit
					4b2eda7d29
				
			
							
								
								
									
										138
									
								
								src/client.rs
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								src/client.rs
									
									
									
									
									
								
							| @@ -11,6 +11,8 @@ use hyper::status::StatusCode; | ||||
| use hyper::version::HttpVersion; | ||||
| use hyper::{Url}; | ||||
|  | ||||
| use hyper_native_tls::{self, NativeTlsClient, native_tls}; | ||||
|  | ||||
| use serde::Serialize; | ||||
| use serde_json; | ||||
| use serde_urlencoded; | ||||
| @@ -47,14 +49,101 @@ pub struct Client { | ||||
|     inner: Arc<ClientRef>, | ||||
| } | ||||
|  | ||||
| impl Client { | ||||
|     /// Constructs a new `Client`. | ||||
|     pub fn new() -> ::Result<Client> { | ||||
|         let mut client = try_!(new_hyper_client()); | ||||
|         client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone); | ||||
| /// Represent an X509 certificate. | ||||
| pub struct Certificate(hyper_native_tls::Certificate); | ||||
|  | ||||
| impl Certificate { | ||||
|     /// Create a `Certificate` from a binary DER encoded certificate | ||||
|     /// | ||||
|     /// # Examples | ||||
|     /// | ||||
|     /// ``` | ||||
|     /// # use std::fs::File; | ||||
|     /// # use std::io::Read; | ||||
|     /// # fn cert() -> Result<(), Box<std::error::Error>> { | ||||
|     /// let mut buf = Vec::new(); | ||||
|     /// File::open("my_cert.der")? | ||||
|     ///     .read_to_end(&mut buf)?; | ||||
|     /// let cert = reqwest::Certificate::from_der(&buf)?; | ||||
|     /// # drop(cert); | ||||
|     /// # Ok(()) | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     pub fn from_der(der: &[u8]) -> ::Result<Certificate> { | ||||
|         let inner = try_!( | ||||
|             hyper_native_tls::Certificate::from_der(der) | ||||
|                 .map_err(|e| ::hyper::Error::Ssl(Box::new(e)))); | ||||
|         Ok(Certificate(inner)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A `ClientBuilder` can be used to create a `Client` with a custom TLS configuration: | ||||
| /// | ||||
| /// - with hostname verification disabled | ||||
| /// - with one or multiple custom certificates | ||||
| /// | ||||
| /// # Examples | ||||
| /// | ||||
| /// ``` | ||||
| /// # use std::fs::File; | ||||
| /// # use std::io::Read; | ||||
| /// # fn build_client() -> Result<(), Box<std::error::Error>> { | ||||
| /// // get a client builder | ||||
| /// let mut client_builder = reqwest::ClientBuilder::new()?; | ||||
| /// | ||||
| /// // read a local binary DER encoded certificate | ||||
| /// let mut buf = Vec::new(); | ||||
| /// File::open("my-cert.der")?.read_to_end(&mut buf)?; | ||||
| /// | ||||
| /// // create a certificate | ||||
| /// let cert = reqwest::Certificate::from_der(&buf)?; | ||||
| /// | ||||
| /// // add the certificate | ||||
| /// client_builder.add_root_certificate(cert)?; | ||||
| /// | ||||
| /// // create the actual client | ||||
| /// let client = client_builder.build()?; | ||||
| /// # drop(client); | ||||
| /// # Ok(()) | ||||
| /// # } | ||||
| /// ``` | ||||
| pub struct ClientBuilder { | ||||
|     inner: native_tls::TlsConnectorBuilder, | ||||
|     hostname_verification: bool, | ||||
| } | ||||
|  | ||||
| impl ClientBuilder { | ||||
|     /// Constructs a new `ClientBuilder` | ||||
|     pub fn new() -> ::Result<ClientBuilder> { | ||||
|         let tls_connector_builder = try_!( | ||||
|             native_tls::TlsConnector::builder() | ||||
|                 .map_err(|e| ::hyper::Error::Ssl(Box::new(e)))); | ||||
|         Ok(ClientBuilder { | ||||
|             inner: tls_connector_builder, | ||||
|             hostname_verification: true, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Returns a `Client` that uses this `ClientBuilder` configuration. | ||||
|     pub fn build(self) -> ::Result<Client> { | ||||
|  | ||||
|         let tls_connector = try_!( | ||||
|             self.inner.build().map_err(|e| ::hyper::Error::Ssl(Box::new(e)))); | ||||
|         let mut tls_client = NativeTlsClient::from(tls_connector); | ||||
|         if ! self.hostname_verification { | ||||
|             tls_client.danger_disable_hostname_verification(true); | ||||
|         } | ||||
|  | ||||
|         let mut hyper_client = ::hyper::Client::with_connector( | ||||
|             ::hyper::client::Pool::with_connector( | ||||
|                 Default::default(), | ||||
|                 ::hyper::net::HttpsConnector::new(tls_client))); | ||||
|  | ||||
|         hyper_client.set_redirect_policy(::hyper::client::RedirectPolicy::FollowNone); | ||||
|  | ||||
|         Ok(Client { | ||||
|             inner: Arc::new(ClientRef { | ||||
|                 hyper: RwLock::new(client), | ||||
|                 hyper: RwLock::new(hyper_client), | ||||
|                 redirect_policy: Mutex::new(RedirectPolicy::default()), | ||||
|                 auto_referer: AtomicBool::new(true), | ||||
|                 auto_ungzip: AtomicBool::new(true), | ||||
| @@ -62,6 +151,31 @@ impl Client { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Add a custom root certificate. This can be used to connect to a server that has a | ||||
|     /// self-signed certificate for example. | ||||
|     pub fn add_root_certificate(&mut self, cert: Certificate) -> ::Result<&mut ClientBuilder> { | ||||
|         try_!(self.inner.add_root_certificate(cert.0) | ||||
|                 .map_err(|e| ::hyper::Error::Ssl(Box::new(e)))); | ||||
|         Ok(self) | ||||
|     } | ||||
|  | ||||
|     /// Disable hostname verification | ||||
|     pub fn danger_disable_hostname_verification(&mut self) { | ||||
|         self.hostname_verification = false; | ||||
|     } | ||||
|  | ||||
|     /// Enable hostname verification | ||||
|     pub fn enable_hostname_verification(&mut self) { | ||||
|         self.hostname_verification = true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Client { | ||||
|     /// Constructs a new `Client`. | ||||
|     pub fn new() -> ::Result<Client> { | ||||
|         try_!(ClientBuilder::new()).build() | ||||
|     } | ||||
|  | ||||
|     /// Enable auto gzip decompression by checking the ContentEncoding response header. | ||||
|     /// | ||||
|     /// Default is enabled. | ||||
| @@ -155,18 +269,6 @@ struct ClientRef { | ||||
|     auto_ungzip: AtomicBool, | ||||
| } | ||||
|  | ||||
| fn new_hyper_client() -> ::Result<::hyper::Client> { | ||||
|     use hyper_native_tls::NativeTlsClient; | ||||
|     Ok(::hyper::Client::with_connector( | ||||
|         ::hyper::client::Pool::with_connector( | ||||
|             Default::default(), | ||||
|             ::hyper::net::HttpsConnector::new( | ||||
|                 try_!(NativeTlsClient::new() | ||||
|                      .map_err(|e| ::hyper::Error::Ssl(Box::new(e))))) | ||||
|         ) | ||||
|     )) | ||||
| } | ||||
|  | ||||
| /// A builder to construct the properties of a `Request`. | ||||
| pub struct RequestBuilder { | ||||
|     client: Arc<ClientRef>, | ||||
|   | ||||
| @@ -154,7 +154,7 @@ pub use hyper::version::HttpVersion; | ||||
| pub use hyper::Url; | ||||
| pub use url::ParseError as UrlError; | ||||
|  | ||||
| pub use self::client::{Client, RequestBuilder}; | ||||
| pub use self::client::{Certificate, Client, ClientBuilder, RequestBuilder}; | ||||
| pub use self::error::{Error, Result}; | ||||
| pub use self::body::Body; | ||||
| pub use self::redirect::RedirectPolicy; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user