如何使用Rust结合hyper crate编写HTTPS服务端?
hyper本身服务端没有内置TLS能力,你需要搭配rustls生态的相关库完成HTTPS适配,具体实现步骤如下:
1. 新增依赖
首先在Cargo.toml中添加以下依赖,版本可根据实际情况更新到最新兼容版:
[dependencies] hyper = { version = "1.0", features = ["full"] } tokio = { version = "1.0", features = ["full"] } rustls = "0.21" rustls-pemfile = "1.0" tokio-rustls = "0.24"
2. 准备TLS证书和私钥
你需要提前准备好PEM格式的TLS证书链文件(通常命名为fullchain.pem)和私钥文件(通常命名为privkey.pem):
- 测试场景可以使用openssl生成自签名证书
- 生产环境使用CA签发的有效公网证书
3. 适配HTTPS的完整代码示例
首先实现证书和私钥的加载逻辑,再替换原有的HTTP服务启动逻辑,修改后的代码如下:
use hyper::{Body, Request, Response, StatusCode}; use hyper::service::{make_service_fn, service_fn}; use std::convert::Infallible; use std::fs::File; use std::io::BufReader; use std::net::SocketAddr; use rustls::{Certificate, PrivateKey, ServerConfig}; use rustls_pemfile::{certs, pkcs8_private_keys}; use tokio_rustls::TlsAcceptor; use tokio::net::TcpListener; // 原有的请求处理逻辑无需修改 async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> { Ok(Response::new(Body::from("Hello HTTPS!"))) } // 加载PEM格式证书 fn load_certs(path: &str) -> Vec<Certificate> { let file = File::open(path).unwrap(); let mut reader = BufReader::new(file); certs(&mut reader).unwrap().into_iter().map(Certificate).collect() } // 加载PEM格式私钥 fn load_private_key(path: &str) -> PrivateKey { let file = File::open(path).unwrap(); let mut reader = BufReader::new(file); pkcs8_private_keys(&mut reader).unwrap().remove(0).into() } async fn runmain() { let addr = SocketAddr::from(([127, 0, 0, 1], 25025)); // 加载证书和私钥,替换为你自己的文件路径 let certs = load_certs("fullchain.pem"); let key = load_private_key("privkey.pem"); // 初始化TLS服务端配置 let config = ServerConfig::builder() .with_safe_defaults() .with_no_client_auth() .with_single_cert(certs, key) .unwrap(); let tls_acceptor = TlsAcceptor::from(std::sync::Arc::new(config)); // 绑定TCP监听器 let listener = TcpListener::bind(&addr).await.unwrap(); println!("HTTPS server running on https://{}", addr); // 循环处理接入的连接 loop { let (stream, _) = listener.accept().await.unwrap(); let tls_acceptor = tls_acceptor.clone(); let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) }); tokio::spawn(async move { // 先完成TLS握手 let tls_stream = match tls_acceptor.accept(stream).await { Ok(s) => s, Err(e) => { eprintln!("TLS handshake failed: {}", e); return; } }; // 把握手后的TLS流交给hyper处理 if let Err(e) = hyper::server::conn::Http::new() .serve_connection(tls_stream, make_svc) .await { eprintln!("HTTP service error: {}", e); } }); } } #[tokio::main] async fn main() { runmain().await; }
注意事项
- 测试自签名证书时浏览器会弹出安全警告,属于正常情况,手动信任证书后即可正常访问
- 生产环境请使用有效期内、由可信CA签发的证书,避免用户访问报错
- rustls默认配置已兼容HTTP/2,不需要额外修改配置即可启用
内容的提问来源于stack exchange,提问作者Hunter
相关产品推荐
相关产品推荐

