use super::service::TlsConnector;
use crate::transport::{
tls::{Certificate, Identity},
Error,
};
use http::Uri;
use tokio_rustls::rustls::pki_types::TrustAnchor;
#[derive(Debug, Clone, Default)]
pub struct ClientTlsConfig {
domain: Option<String>,
certs: Vec<Certificate>,
trust_anchors: Vec<TrustAnchor<'static>>,
identity: Option<Identity>,
assume_http2: bool,
#[cfg(feature = "tls-native-roots")]
with_native_roots: bool,
#[cfg(feature = "tls-webpki-roots")]
with_webpki_roots: bool,
}
impl ClientTlsConfig {
pub fn new() -> Self {
Self::default()
}
pub fn domain_name(self, domain_name: impl Into<String>) -> Self {
ClientTlsConfig {
domain: Some(domain_name.into()),
..self
}
}
pub fn ca_certificate(self, ca_certificate: Certificate) -> Self {
let mut certs = self.certs;
certs.push(ca_certificate);
ClientTlsConfig { certs, ..self }
}
pub fn ca_certificates(self, ca_certificates: impl IntoIterator<Item = Certificate>) -> Self {
let mut certs = self.certs;
certs.extend(ca_certificates);
ClientTlsConfig { certs, ..self }
}
pub fn trust_anchor(self, trust_anchor: TrustAnchor<'static>) -> Self {
let mut trust_anchors = self.trust_anchors;
trust_anchors.push(trust_anchor);
ClientTlsConfig {
trust_anchors,
..self
}
}
pub fn trust_anchors(
mut self,
trust_anchors: impl IntoIterator<Item = TrustAnchor<'static>>,
) -> Self {
self.trust_anchors.extend(trust_anchors);
self
}
pub fn identity(self, identity: Identity) -> Self {
ClientTlsConfig {
identity: Some(identity),
..self
}
}
pub fn assume_http2(self, assume_http2: bool) -> Self {
ClientTlsConfig {
assume_http2,
..self
}
}
#[cfg(feature = "tls-native-roots")]
pub fn with_native_roots(self) -> Self {
ClientTlsConfig {
with_native_roots: true,
..self
}
}
#[cfg(feature = "tls-webpki-roots")]
pub fn with_webpki_roots(self) -> Self {
ClientTlsConfig {
with_webpki_roots: true,
..self
}
}
pub fn with_enabled_roots(self) -> Self {
let config = ClientTlsConfig::new();
#[cfg(feature = "tls-native-roots")]
let config = config.with_native_roots();
#[cfg(feature = "tls-webpki-roots")]
let config = config.with_webpki_roots();
config
}
pub(crate) fn into_tls_connector(self, uri: &Uri) -> Result<TlsConnector, crate::Error> {
let domain = match &self.domain {
Some(domain) => domain,
None => uri.host().ok_or_else(Error::new_invalid_uri)?,
};
TlsConnector::new(
self.certs,
self.trust_anchors,
self.identity,
domain,
self.assume_http2,
#[cfg(feature = "tls-native-roots")]
self.with_native_roots,
#[cfg(feature = "tls-webpki-roots")]
self.with_webpki_roots,
)
}
}