|
use hyper::{Request, Response, body::Incoming}; |
|
use hyper::service::service_fn; |
|
use hyper_util::rt::TokioIo; |
|
use hyper_util::server::conn::auto::Builder; |
|
use tokio::net::TcpListener; |
|
use tokio_rustls::TlsAcceptor; |
|
use rustls::ServerConfig; |
|
use rustls_pemfile::{certs, pkcs8_private_keys}; |
|
use std::convert::Infallible; |
|
use std::sync::Arc; |
|
use std::fs::File; |
|
use std::io::BufReader; |
|
|
|
async fn handle_request(_req: Request<Incoming>) -> Result<Response<String>, Infallible> { |
|
Ok(Response::new("Hello, World!".to_string())) |
|
} |
|
|
|
fn load_certs(path: &str) -> Result<Vec<rustls::pki_types::CertificateDer<'static>>, Box<dyn std::error::Error>> { |
|
let file = File::open(path)?; |
|
let mut reader = BufReader::new(file); |
|
let certs = certs(&mut reader).collect::<Result<Vec<_>, _>>()?; |
|
Ok(certs) |
|
} |
|
|
|
fn load_keys(path: &str) -> Result<rustls::pki_types::PrivateKeyDer<'static>, Box<dyn std::error::Error>> { |
|
let file = File::open(path)?; |
|
let mut reader = BufReader::new(file); |
|
let mut keys = pkcs8_private_keys(&mut reader).collect::<Result<Vec<_>, _>>()?; |
|
if keys.is_empty() { |
|
return Err("No private keys found".into()); |
|
} |
|
Ok(rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0))) |
|
} |
|
|
|
#[tokio::main] |
|
async fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
let addr = "127.0.0.1:3443"; |
|
|
|
// TLS設定 |
|
let certs = load_certs("localhost.pem")?; |
|
let key = load_keys("localhost-key.pem")?; |
|
|
|
let mut config = ServerConfig::builder() |
|
.with_no_client_auth() |
|
.with_single_cert(certs, key)?; |
|
|
|
config.alpn_protocols = vec![ |
|
b"h2".to_vec(), |
|
b"http/1.1".to_vec() |
|
]; |
|
|
|
let acceptor = TlsAcceptor::from(Arc::new(config)); |
|
let listener = TcpListener::bind(addr).await?; |
|
|
|
println!("Listening on https://{}", addr); |
|
|
|
loop { |
|
let (stream, _) = listener.accept().await?; |
|
let acceptor = acceptor.clone(); |
|
|
|
tokio::spawn(async move { |
|
// TLSハンドシェイク |
|
let tls_stream = match acceptor.accept(stream).await { |
|
Ok(stream) => stream, |
|
Err(err) => { |
|
eprintln!("TLS handshake error: {:?}", err); |
|
return; |
|
} |
|
}; |
|
|
|
let io = TokioIo::new(tls_stream); |
|
|
|
if let Err(err) = Builder::new(hyper_util::rt::TokioExecutor::new()) |
|
.serve_connection(io, service_fn(handle_request)) |
|
.await |
|
{ |
|
eprintln!("Error serving connection: {:?}", err); |
|
} |
|
}); |
|
} |
|
} |