use std::sync::Arc;
use hyper_rustls::HttpsConnectorBuilder;
use rustls::pki_types::pem::PemObject;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::TlsAcceptor;
use crate::{ProxyError, Result, TlsConfig};
pub fn build_tls_acceptor(config: &TlsConfig) -> Result<TlsAcceptor> {
let certs = load_certs(&config.cert_path)?;
let key = load_private_key(&config.key_path)?;
let server_config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)
.map_err(|e| ProxyError::Tls(format!("failed to build TLS server config: {e}")))?;
Ok(TlsAcceptor::from(Arc::new(server_config)))
}
pub fn build_https_connector()
-> hyper_rustls::HttpsConnector<hyper_util::client::legacy::connect::HttpConnector> {
let root_store =
rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
let tls_config = rustls::ClientConfig::builder()
.with_root_certificates(root_store)
.with_no_client_auth();
HttpsConnectorBuilder::new()
.with_tls_config(tls_config)
.https_or_http()
.enable_http1()
.build()
}
fn load_certs(path: &str) -> Result<Vec<CertificateDer<'static>>> {
CertificateDer::pem_file_iter(path)
.map_err(|e| ProxyError::Tls(format!("failed to open cert file {path}: {e}")))?
.collect::<std::result::Result<Vec<_>, _>>()
.map_err(|e| ProxyError::Tls(format!("failed to parse certificates from {path}: {e}")))
}
fn load_private_key(path: &str) -> Result<PrivateKeyDer<'static>> {
PrivateKeyDer::from_pem_file(path)
.map_err(|e| ProxyError::Tls(format!("failed to load private key from {path}: {e}")))
}