如何创建支持TLS(HTTPS)的Mock HTTP测试服务器?
实现支持HTTPS的测试回显服务器
由于mockito等工具不原生支持TLS,我们可以用hyper + rustls + rcgen组合搭建纯Rust的HTTPS测试服务器,完全复刻原mockito的回显逻辑,且无需依赖外部服务。
步骤1:添加依赖
在Cargo.toml中添加所需依赖:
[dependencies] hyper = { version = "1.1", features = ["full"] } rustls = "0.22" rcgen = "0.11" tokio = { version = "1.0", features = ["full"] } reqwest = { version = "0.11", features = ["rustls-tls"] } hyper-rustls = "0.24" http = "1.0"
步骤2:生成自签名测试证书
用rcgen动态生成自签名证书,无需提前准备证书文件:
use rcgen::{Certificate, CertificateParams, DnType}; use rustls::ServerConfig; use rustls_pemfile::{certs, pkcs8_private_keys}; use std::io::Cursor; fn generate_self_signed_cert() -> ServerConfig { // 配置证书参数,指定localhost为域名 let mut params = CertificateParams::new(vec!["localhost".to_string()]); params.distinguished_name.push(DnType::CommonName, "localhost"); let cert = Certificate::from_params(params).unwrap(); let cert_pem = cert.serialize_pem().unwrap(); let key_pem = cert.serialize_private_key_pem(); // 解析证书和私钥为rustls可识别的格式 let cert_chain = certs(&mut Cursor::new(cert_pem)).unwrap(); let mut keys = pkcs8_private_keys(&mut Cursor::new(key_pem)).unwrap(); let mut config = ServerConfig::builder() .with_safe_defaults() .with_no_client_auth() .with_single_cert(cert_chain, keys.remove(0)).unwrap(); // 启用HTTP/1.1 ALPN协议 config.alpn_protocols = vec![b"http/1.1".to_vec()]; config }
步骤3:搭建HTTPS回显服务器
基于hyper实现和原mockito逻辑一致的回显功能:
use hyper::{Body, Request, Response, Server, StatusCode}; use hyper::service::{make_service_fn, service_fn}; use std::convert::Infallible; use std::net::SocketAddr; async fn echo_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> { let path = req.uri().path(); // 匹配/echo/前缀的路径,返回后续内容 if let Some(echo_content) = path.strip_prefix("/echo/") { Ok(Response::new(Body::from(echo_content))) } else { Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("Not Found")) .unwrap()) } } async fn start_tls_server() -> (String, impl futures::Future<Output = ()>) { // 使用随机端口避免冲突 let addr = SocketAddr::from(([127, 0, 0, 1], 0)); let tls_config = generate_self_signed_cert(); // 创建服务处理函数 let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(echo_handler)) }); // 启动TLS服务器 let server = Server::builder(hyper_rustls::TlsAcceptor::new(tls_config, addr)) .serve(make_svc); let server_addr = server.local_addr(); let server_url = format!("https://{}", server_addr); // 返回服务器URL和运行未来对象 (server_url, server) }
步骤4:编写测试用例
启动HTTPS服务器,配置reqwest客户端信任自签名证书,完成测试:
#[tokio::test] async fn test_https_echo() { let (server_url, server_future) = start_tls_server().await; // 在后台异步运行服务器 tokio::spawn(async move { if let Err(e) = server_future.await { eprintln!("Server error: {}", e); } }); // 配置reqwest客户端信任我们生成的自签名证书 let tls_config = generate_self_signed_cert(); let mut root_certs = rustls::RootCertStore::empty(); for cert_der in tls_config.cert_chain.iter() { root_certs.add(&rustls::Certificate(cert_der.clone())).unwrap(); } let client_tls_config = rustls::ClientConfig::builder() .with_safe_defaults() .with_root_certificates(root_certs) .with_no_client_auth(); let client = reqwest::Client::builder() .use_preconfigured_tls(client_tls_config) .build().unwrap(); // 发送请求并验证回显结果 let resp = client.get(format!("{}/echo/foobar", server_url)) .send().await.unwrap() .text().await.unwrap(); assert_eq!(resp, "foobar"); }
方案优势
- 纯Rust实现,无外部依赖,测试环境稳定
- 动态生成证书,无需手动管理测试证书文件
- 完全复刻原mockito的回显逻辑,无缝替换原有测试
- 支持异步/同步场景(示例用异步,如需同步可调整reqwest为blocking客户端)
内容的提问来源于stack exchange,提问作者ChrisB
相关产品推荐
相关产品推荐

