use anyhow::Result;
use async_stream::stream;
use futures::TryFutureExt;
use hyper::server::accept::Accept;
use hyper::server::Builder;
use rustls::{Certificate, PrivateKey, ServerConfig};
use std::io::Error;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::{TcpListener, TcpStream};
use tokio_rustls::server::TlsStream;
use tokio_rustls::TlsAcceptor;
pub struct Https {
cert: Vec<Certificate>,
key: PrivateKey,
}
impl Https {
pub fn new(cert: Vec<Certificate>, key: PrivateKey) -> Self {
Https { cert, key }
}
fn make_tls_cfg(&self) -> Result<Arc<ServerConfig>> {
let (certs, private_key) = (self.cert.clone(), self.key.clone());
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certs, private_key)
.map_err(anyhow::Error::new)?;
Ok(Arc::new(config))
}
pub async fn make_server(
&self,
addr: SocketAddr,
) -> Result<Builder<impl Accept<Conn = TlsStream<TcpStream>, Error = Error>>> {
let tcp = TcpListener::bind(addr).await?;
let tls_cfg = self.make_tls_cfg()?;
let tls_acceptor = TlsAcceptor::from(tls_cfg);
let incoming_tls_stream = stream! {
loop {
let (socket, _) = tcp.accept().await?;
let stream = tls_acceptor.accept(socket).map_err(|error| {
println!("HTTPS Error: {:?}", error);
error
});
yield stream.await;
}
};
let acceptor = hyper::server::accept::from_stream(incoming_tls_stream);
let server = hyper::server::Server::builder(acceptor);
Ok(server)
}
}