Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Created November 16, 2025 22:54
Show Gist options
  • Select an option

  • Save masakielastic/68a1991383d4dab5ec4b4103fad332f1 to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/68a1991383d4dab5ec4b4103fad332f1 to your computer and use it in GitHub Desktop.
warp v0.4 で HTTP/1 +TLS サーバー (Filter からサービスの作成)

warp v0.4 で HTTP/1 +TLS サーバー (Filter からサービスの作成)

構成

  • Cargo.tmol
  • src/main.rs

実行

cargo run を実行します。 ブラウザーや curl でアクセスします。

curl -kv https://localhost:3000
[package]
name = "warp-project"
version = "0.1.0"
edition = "2021"
[dependencies]
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
hyper-util = { version = "0.1", features = ["full"] }
warp = { version = "0.4", default-features = false }
tokio-rustls = "0.26"
rustls = "0.23"
rustls-pemfile = "2"
use std::{net::SocketAddr, sync::Arc};
use std::fs::File;
use std::io::BufReader;
use hyper::server::conn::http1;
use hyper_util::rt::TokioIo;
use hyper_util::service::TowerToHyperService;
use tokio::net::TcpListener;
use warp::Filter;
use rustls::ServerConfig;
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
use rustls_pemfile::{certs, pkcs8_private_keys};
use tokio_rustls::TlsAcceptor;
fn load_tls_config() -> Result<Arc<ServerConfig>, Box<dyn std::error::Error + Send + Sync>> {
// 証明書と鍵ファイルを開く
let cert_file = &mut BufReader::new(File::open("localhost.pem")?);
let key_file = &mut BufReader::new(File::open("localhost-key.pem")?);
// --- 証明書チェーンを Vec<CertificateDer> に読む ---
let cert_chain: Vec<CertificateDer<'static>> = certs(cert_file)
.collect::<Result<Vec<_>, _>>()?; // ← イテレータを Result<Vec<_>, _> にまとめてから ? する
// --- 秘密鍵 (PKCS#8) を Vec<PrivatePkcs8KeyDer> に読む ---
let mut keys: Vec<PrivatePkcs8KeyDer<'static>> = pkcs8_private_keys(key_file)
.collect::<Result<Vec<_>, _>>()?;
if keys.is_empty() {
return Err("private key not found in key.pem".into());
}
// rustls が要求する PrivateKeyDer に変換
let key_der: PrivateKeyDer<'static> = PrivateKeyDer::from(keys.remove(0));
// ServerConfig を組み立て
let config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(cert_chain, key_der)?; // ← ここに上の型を渡す
Ok(Arc::new(config))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// warp のルーティングはそのまま
let routes = warp::any().map(|| "Hello, World!".to_string());
let tower_svc = warp::service(routes);
let hyper_svc = TowerToHyperService::new(tower_svc);
// TLS 設定読み込み
let tls_config = load_tls_config()?;
let tls_acceptor = TlsAcceptor::from(tls_config);
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
let listener = TcpListener::bind(addr).await?;
println!("HTTPS server listening on https://{addr}");
loop {
let (stream, _peer) = listener.accept().await?;
let io = stream;
let svc = hyper_svc.clone();
let acceptor = tls_acceptor.clone();
tokio::spawn(async move {
// ここで TLS ハンドシェイク
let tls_stream = match acceptor.accept(io).await {
Ok(s) => s,
Err(err) => {
eprintln!("TLS accept error: {err}");
return;
}
};
let io = TokioIo::new(tls_stream);
if let Err(err) = http1::Builder::new()
.serve_connection(io, svc)
.await
{
eprintln!("error serving connection: {err}");
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment