use std::path::Path;
use std::sync::Arc;
use rustls_pki_types::pem::PemObject;
use rustls_pki_types::{CertificateDer, PrivateKeyDer};
use thiserror::Error;
use tokio_rustls::rustls;
#[derive(Error, Debug)]
pub enum TlsAcceptorError {
#[error("invalid pem data")]
InvalidPem(#[from] rustls_pki_types::pem::Error),
#[error("failed to create ServerConfig")]
ServerConfig(#[from] rustls::Error),
#[error("failed to read file")]
FileRead(#[source] std::io::Error),
}
pub async fn get_tlsacceptor_from_files(
cert_path: impl AsRef<Path> + Send,
key_path: impl AsRef<Path> + Send,
) -> Result<tokio_rustls::TlsAcceptor, TlsAcceptorError> {
let cert_data = tokio::fs::read(cert_path)
.await
.map_err(TlsAcceptorError::FileRead)?;
let key_data = tokio::fs::read(key_path)
.await
.map_err(TlsAcceptorError::FileRead)?;
get_tlsacceptor_from_pem_data(&cert_data, &key_data)
}
pub fn get_tlsacceptor_from_pem_data(
cert_data: &[u8],
key_data: &[u8],
) -> Result<tokio_rustls::TlsAcceptor, TlsAcceptorError> {
let certs: Vec<_> = CertificateDer::pem_slice_iter(cert_data).collect::<Result<_, _>>()?;
let key = PrivateKeyDer::from_pem_slice(key_data)?;
let mut cfg = rustls::server::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)?;
cfg.alpn_protocols = vec![b"http/1.1".to_vec(), b"http/1.0".to_vec()];
let acceptor = tokio_rustls::TlsAcceptor::from(Arc::new(cfg));
Ok(acceptor)
}