add ability to create a client with own tls connector (#809)
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
#[cfg(feature = "__tls")]
|
||||||
|
use std::any::Any;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -188,6 +190,7 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Connector::new_default_tls(
|
Connector::new_default_tls(
|
||||||
tls,
|
tls,
|
||||||
proxies.clone(),
|
proxies.clone(),
|
||||||
@@ -195,7 +198,25 @@ impl ClientBuilder {
|
|||||||
config.local_address,
|
config.local_address,
|
||||||
config.nodelay,
|
config.nodelay,
|
||||||
)?
|
)?
|
||||||
}
|
},
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
TlsBackend::BuiltDefault(conn) => {
|
||||||
|
Connector::from_built_default(
|
||||||
|
conn,
|
||||||
|
proxies.clone(),
|
||||||
|
user_agent(&config.headers),
|
||||||
|
config.local_address,
|
||||||
|
config.nodelay)?
|
||||||
|
},
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
TlsBackend::BuiltRustls(conn) => {
|
||||||
|
Connector::new_rustls_tls(
|
||||||
|
conn,
|
||||||
|
proxies.clone(),
|
||||||
|
user_agent(&config.headers),
|
||||||
|
config.local_address,
|
||||||
|
config.nodelay)?
|
||||||
|
},
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
TlsBackend::Rustls => {
|
TlsBackend::Rustls => {
|
||||||
use crate::tls::NoVerifier;
|
use crate::tls::NoVerifier;
|
||||||
@@ -229,7 +250,12 @@ impl ClientBuilder {
|
|||||||
config.local_address,
|
config.local_address,
|
||||||
config.nodelay,
|
config.nodelay,
|
||||||
)?
|
)?
|
||||||
}
|
},
|
||||||
|
TlsBackend::UnknownPreconfigured => {
|
||||||
|
return Err(crate::error::builder(
|
||||||
|
"Unknown TLS backend passed to `use_preconfigured_tls`"
|
||||||
|
));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "__tls"))]
|
#[cfg(not(feature = "__tls"))]
|
||||||
@@ -711,6 +737,38 @@ impl ClientBuilder {
|
|||||||
self.config.tls = TlsBackend::Rustls;
|
self.config.tls = TlsBackend::Rustls;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use a preconfigured TLS backend.
|
||||||
|
///
|
||||||
|
/// If the passed `Any` argument is not a TLS backend that reqwest
|
||||||
|
/// understands, the `ClientBuilder` will error when calling `build`.
|
||||||
|
#[cfg(feature = "__tls")]
|
||||||
|
pub fn use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder {
|
||||||
|
let mut tls = Some(tls);
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
{
|
||||||
|
if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<native_tls_crate::TlsConnector>>() {
|
||||||
|
let tls = conn.take().expect("is definitely Some");
|
||||||
|
let tls = crate::tls::TlsBackend::BuiltDefault(tls);
|
||||||
|
self.config.tls = tls;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
{
|
||||||
|
if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>() {
|
||||||
|
|
||||||
|
let tls = conn.take().expect("is definitely Some");
|
||||||
|
let tls = crate::tls::TlsBackend::BuiltRustls(tls);
|
||||||
|
self.config.tls = tls;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we don't recognize the TLS backend!
|
||||||
|
self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type HyperClient = hyper::Client<Connector, super::body::ImplStream>;
|
type HyperClient = hyper::Client<Connector, super::body::ImplStream>;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::any::Any;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
@@ -450,6 +451,15 @@ impl ClientBuilder {
|
|||||||
self.with_inner(move |inner| inner.use_rustls_tls())
|
self.with_inner(move |inner| inner.use_rustls_tls())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use a preconfigured TLS backend.
|
||||||
|
///
|
||||||
|
/// If the passed `Any` argument is not a TLS backend that reqwest
|
||||||
|
/// understands, the `ClientBuilder` will error when calling `build`.
|
||||||
|
#[cfg(feature = "__tls")]
|
||||||
|
pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {
|
||||||
|
self.with_inner(move |inner| inner.use_preconfigured_tls(tls))
|
||||||
|
}
|
||||||
|
|
||||||
// private
|
// private
|
||||||
|
|
||||||
fn with_inner<F>(mut self, func: F) -> ClientBuilder
|
fn with_inner<F>(mut self, func: F) -> ClientBuilder
|
||||||
|
|||||||
@@ -107,6 +107,31 @@ impl Connector {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
pub(crate) fn from_built_default<T> (
|
||||||
|
tls: TlsConnector,
|
||||||
|
proxies: Arc<Vec<Proxy>>,
|
||||||
|
user_agent: Option<HeaderValue>,
|
||||||
|
local_addr: T,
|
||||||
|
nodelay: bool) -> crate::Result<Connector>
|
||||||
|
where
|
||||||
|
T: Into<Option<IpAddr>>,
|
||||||
|
{
|
||||||
|
|
||||||
|
let mut http = http_connector()?;
|
||||||
|
http.set_local_address(local_addr.into());
|
||||||
|
http.enforce_http(false);
|
||||||
|
|
||||||
|
Ok(Connector {
|
||||||
|
inner: Inner::DefaultTls(http, tls),
|
||||||
|
proxies,
|
||||||
|
verbose: verbose::OFF,
|
||||||
|
timeout: None,
|
||||||
|
nodelay,
|
||||||
|
user_agent,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
pub(crate) fn new_rustls_tls<T>(
|
pub(crate) fn new_rustls_tls<T>(
|
||||||
tls: rustls::ClientConfig,
|
tls: rustls::ClientConfig,
|
||||||
|
|||||||
22
src/tls.rs
22
src/tls.rs
@@ -266,12 +266,32 @@ impl fmt::Debug for Identity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) enum TlsBackend {
|
pub(crate) enum TlsBackend {
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
Default,
|
Default,
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
BuiltDefault(native_tls_crate::TlsConnector),
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
Rustls,
|
Rustls,
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
BuiltRustls(rustls::ClientConfig),
|
||||||
|
UnknownPreconfigured,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for TlsBackend {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
TlsBackend::Default => write!(f, "Default"),
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
TlsBackend::BuiltDefault(_) => write!(f, "BuiltDefault"),
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
TlsBackend::Rustls => write!(f, "Rustls"),
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
TlsBackend::BuiltRustls(_) => write!(f, "BuiltRustls"),
|
||||||
|
TlsBackend::UnknownPreconfigured => write!(f, "UnknownPreconfigured"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TlsBackend {
|
impl Default for TlsBackend {
|
||||||
|
|||||||
@@ -133,3 +133,42 @@ async fn body_pipe_response() {
|
|||||||
|
|
||||||
assert_eq!(res2.status(), reqwest::StatusCode::OK);
|
assert_eq!(res2.status(), reqwest::StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "__tls")]
|
||||||
|
#[test]
|
||||||
|
fn use_preconfigured_tls_with_bogus_backend() {
|
||||||
|
struct DefinitelyNotTls;
|
||||||
|
|
||||||
|
reqwest::Client::builder()
|
||||||
|
.use_preconfigured_tls(DefinitelyNotTls)
|
||||||
|
.build()
|
||||||
|
.expect_err("definitely is not TLS");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "default-tls")]
|
||||||
|
#[test]
|
||||||
|
fn use_preconfigured_native_tls_default() {
|
||||||
|
extern crate native_tls_crate;
|
||||||
|
|
||||||
|
let tls = native_tls_crate::TlsConnector::builder()
|
||||||
|
.build()
|
||||||
|
.expect("tls builder");
|
||||||
|
|
||||||
|
reqwest::Client::builder()
|
||||||
|
.use_preconfigured_tls(tls)
|
||||||
|
.build()
|
||||||
|
.expect("preconfigured default tls");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
#[test]
|
||||||
|
fn use_preconfigured_rustls_default() {
|
||||||
|
extern crate rustls;
|
||||||
|
|
||||||
|
let tls = rustls::ClientConfig::new();
|
||||||
|
|
||||||
|
reqwest::Client::builder()
|
||||||
|
.use_preconfigured_tls(tls)
|
||||||
|
.build()
|
||||||
|
.expect("preconfigured rustls tls");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user