use actix_http::Uri;
use awc::{Client, error::HttpError};
use log::info;
use rustls::ClientConfig;
use std::sync::Arc;
use tokio_rustls::rustls::{
RootCertStore,
pki_types::{CertificateDer, PrivateKeyDer, TrustAnchor},
};
use crate::{WStompClient, WStompConfig, WStompConnectError};
pub async fn connect_ssl<U>(url: U) -> Result<WStompClient, WStompConnectError>
where
Uri: TryFrom<U>,
<Uri as TryFrom<U>>::Error: Into<HttpError>,
{
WStompConfig::new(url).ssl().build_and_connect().await
}
pub async fn connect_ssl_with_token<U>(
url: U,
auth_token: impl Into<String>,
) -> Result<WStompClient, WStompConnectError>
where
Uri: TryFrom<U>,
<Uri as TryFrom<U>>::Error: Into<HttpError>,
{
WStompConfig::new(url)
.ssl()
.auth_token(auth_token)
.build_and_connect()
.await
}
pub async fn connect_ssl_with_pass<U>(
url: U,
login: String,
passcode: String,
) -> Result<WStompClient, WStompConnectError>
where
Uri: TryFrom<U>,
<Uri as TryFrom<U>>::Error: Into<HttpError>,
{
WStompConfig::new(url)
.ssl()
.login(login)
.passcode(passcode)
.build_and_connect()
.await
}
pub async fn connect_ssl_with_cert<U>(
url: U,
cert_chain: Vec<CertificateDer<'static>>,
key_der: PrivateKeyDer<'static>,
ca_certs: Vec<CertificateDer<'static>>,
) -> Result<WStompClient, WStompConnectError>
where
Uri: TryFrom<U>,
<Uri as TryFrom<U>>::Error: Into<HttpError>,
{
WStompConfig::new(url)
.ssl()
.cert(cert_chain)
.key(key_der)
.ca_certs(ca_certs)
.build_and_connect()
.await
}
pub(crate) fn create_ssl_client(
cert_chain: Option<Vec<CertificateDer<'static>>>,
key_der: Option<Arc<PrivateKeyDer<'static>>>,
ca_certs: Option<Vec<CertificateDer<'static>>>,
) -> Client {
let mut root_store = RootCertStore::empty();
if let Some(ca_certs) = ca_certs {
for cert in ca_certs {
match root_store.add(cert) {
Ok(()) => info!("Successfully added CA certificate."),
Err(error) => panic!("Error adding CA certificate: {error}"),
}
}
} else {
root_store.extend(
webpki_roots::TLS_SERVER_ROOTS
.iter()
.cloned()
.map(|ta| TrustAnchor {
subject: ta.subject,
subject_public_key_info: ta.subject_public_key_info,
name_constraints: ta.name_constraints,
}),
);
}
let config_builder = ClientConfig::builder().with_root_certificates(root_store);
let mut config = if let (Some(cert), Some(key)) = (cert_chain, key_der) {
match config_builder.with_client_auth_cert(cert, key.clone_key()) {
Ok(config) => config,
Err(error) => {
panic!("Error initializing TLS client certificate authentication. {error:?}");
}
}
} else {
config_builder.with_no_client_auth()
};
config.alpn_protocols = vec![b"http/1.1".to_vec()];
let connector = awc::Connector::new().rustls_0_23(Arc::new(config));
Client::builder().connector(connector).finish()
}