Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Created November 17, 2025 05:23
Show Gist options
  • Select an option

  • Save masakielastic/6cee30530d2ca6d9cb2632f25bca578f to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/6cee30530d2ca6d9cb2632f25bca578f to your computer and use it in GitHub Desktop.

hyper で HTTP + TLS サーバー

構成

  • Cargo.toml
  • src/main.rs

実行

cargo run

アクセス

curl -kv https://localhost:3443
[package]
name = "hyper-minimal"
version = "0.1.0"
edition = "2024"
[dependencies]
hyper = { version = "1.5", features = ["server", "http1", "http2"] }
hyper-util = { version = "0.1", features = ["tokio", "server", "http1", "http2"] }
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.26"
rustls = "0.23"
rustls-pemfile = "2.0"
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);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment