- 后端
- 网络
【免费下载链接】cpp-httplib
A C++ header-only HTTP/HTTPS server and client library
cpp-httplib 的httplib::Client同时支持明文 HTTP 与加密 HTTPS 通信。本文基于官方 Tour 文档的「HTTPS Client」章节,完整讲解如何用一行https://前缀切换协议、处理 HTTPS 默认端口、控制 CA 证书校验策略,以及开启重定向自动追踪;同时结合仓库源码与测试用例,揭示这些 API 背后的实现机制,让你在真实项目中安全、正确地使用 HTTPS 客户端。
前置准备:开启 TLS 支持
在写出第一个 HTTPS 客户端之前,需要确保编译时启用了 TLS 后端。cpp-httplib 以CPPHTTPLIB_OPENSSL_SUPPORT宏开关 TLS 功能,并链接 OpenSSL 的libssl与libcrypto两个库(Linux 下典型编译命令如下):
clang++ -std=c++17 -pthread -DCPPHTTPLIB_OPENSSL_SUPPORT \ -lssl -lcrypto \ -o client client.cppmacOS 下还需借助-I/-L指定 Homebrew 版 OpenSSL 路径,并通过-framework CoreFoundation -framework Security让 Keychain 中的系统证书可被自动读取。除 OpenSSL 外,项目还支持 Mbed TLS(CPPHTTPLIB_MBEDTLS_SUPPORT)与 wolfSSL(CPPHTTPLIB_WOLFSSL_SUPPORT),切换方式仅涉及宏定义与链接库名,客户端 API 完全一致。完整的安装与编译选项对照可参见 05-tls-setup。
从 http 到 https:只改一个 URL 前缀
在 02-basic-client 中,我们使用httplib::Client cli("http://localhost:8080")发送明文请求。切换到 HTTPS 时,只需把构造函数的 URL 前缀改为https://,其余 API(Get()、Post()、参数传递、响应读取等)全部保持不变:
#define CPPHTTPLIB_OPENSSL_SUPPORT #include "httplib.h" #include <iostream> int main() { httplib::Client cli("https://nghttp2.org"); auto res = cli.Get("/"); if (res) { std::cout << res->status << std::endl; // 200 std::cout << res->body.substr(0, 100) << std::endl; // HTML 开头部分 } else { std::cout << "Error: " << httplib::to_string(res.error()) << std::endl; } }对应的curl命令同样只换协议前缀:
curl https://nghttp2.org/从源码结构看,httplib::Client在解析 URL 时会根据 scheme 自动选择加密传输路径;仓库 example/client.cc 中也提供了直接使用httplib::SSLClient的另一种写法(SSLClient cli("localhost", 8080)),便于显式声明 TLS 连接。无论哪种方式,只要在#include "httplib.h"之前定义了CPPHTTPLIB_OPENSSL_SUPPORT,客户端即可完成 TLS 握手。
指定端口:HTTPS 默认端口 443
HTTPS 的默认端口是 443。当服务器监听在其他端口(例如本地开发常用的 8443)时,直接在 URL 中写明端口即可:
httplib::Client cli("https://localhost:8443");该默认值在实现中亦有体现:在重定向跳转等场景下,当 URL 未显式携带端口时,实现代码会按next_scheme == "https" ? 443 : 80补齐端口(见 httplib.h),与 HTTP 默认端口 80 形成对应。
CA 证书验证:默认开启,自动读取系统信任库
httplib::Client建立 HTTPS 连接时,默认会对服务器证书进行验证,只信任由受信 CA(证书颁发机构)签发的证书。CA 证书的加载是自动完成的:
- macOS:从 Keychain 读取;
- Linux:从系统 CA 证书存储读取;
- Windows:从 Windows 证书存储读取。
大多数情况下无需任何额外配置。源码中该行为由enable_system_ca(bool)与system_ca_mode_(SystemCAMode::Enabled/Disabled)控制(见 httplib.h);macOS 上自动读取 Keychain 依赖编译时的-framework CoreFoundation -framework Security链接选项。
手动指定 CA 证书文件
某些环境(如精简容器、嵌入式系统)可能找不到系统 CA 证书,此时可用set_ca_cert_path()显式指定证书文件路径:
httplib::Client cli("https://nghttp2.org"); cli.set_ca_cert_path("/etc/ssl/certs/ca-certificates.crt"); auto res = cli.Get("/");对应的 curl 参数为--cacert:
curl --cacert /etc/ssl/certs/ca-certificates.crt https://nghttp2.org/值得留意的是,set_ca_cert_path()的实现签名带有两个参数——证书文件路径与证书目录路径(见 httplib.h):
inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path, const std::string &ca_cert_dir_path);日常用法只传第一个参数即可;第二个参数可用于指定存放多个 CA 证书的目录,适合需要同时信任多个证书源的场景。仓库 example/client.cc 中的实际用法是配合随仓库提供的 example/ca-bundle.crt:
cli.set_ca_cert_path(CA_CERT_FILE); // CA_CERT_FILE = "./ca-bundle.crt" cli.enable_server_certificate_verification(true);测试套件 test/test.cc 同样通过set_ca_cert_path(CA_CERT_FILE)+ 开启验证的组合来校验 HTTPS 客户端行为,可作为集成范例。
开发期禁用证书验证
在开发阶段连接自签名证书的服务器(如本地localhost:8443使用测试证书)时,可以临时关闭验证:
httplib::Client cli("https://localhost:8443"); cli.enable_server_certificate_verification(false); auto res = cli.Get("/");curl 的等价写法是-k(或--insecure):
curl -k https://localhost:8443/生产环境绝不要关闭证书验证,否则中间人攻击(MITM)可以轻松伪造服务器身份,窃取或篡改通信内容。测试代码 test/test.cc 中大量enable_server_certificate_verification(false)调用均用于本地自签名证书的测试场景,这正是它适合出现的位置——测试环境,而非线上。
重定向追踪:默认不追,开启后自动跟进
访问真实网站时常会遇到重定向:http://跳转到https://、www域名跳转到非www域名、路径迁移等。cpp-httplib 的客户端默认不自动追踪重定向,此时响应会停留在 3xx 状态码,重定向目标位于Location响应头中:
httplib::Client cli("https://nghttp2.org"); auto res = cli.Get("/httpbin/redirect/3"); if (res) { std::cout << res->status << std::endl; // 302 std::cout << res->get_header_value("Location") << std::endl; }curl https://nghttp2.org/httpbin/redirect/3调用set_follow_location(true)后,客户端会自动追踪重定向并返回最终响应:
httplib::Client cli("https://nghttp2.org"); cli.set_follow_location(true); auto res = cli.Get("/httpbin/redirect/3"); if (res) { std::cout << res->status << std::endl; // 200(最终响应) }curl -L https://nghttp2.org/httpbin/redirect/3源码层面的重定向实现
深入 httplib.h 的ClientImpl::redirect()实现,可以看到自动追踪的若干关键行为:
- 只跟随 http/https:
Location指向的 URL 若使用其他 scheme,直接放弃跳转,防止协议混淆; - 相对路径解析:
Location为相对路径(如/redirect/3)时会基于当前请求路径解析出完整目标; - 同主机复用连接:目标与当前请求 scheme、host、port 一致时,复用当前客户端继续发送请求;
- 跨主机新建客户端:跳转到其他主机/端口时,会创建新的客户端实例(HTTPS 目标创建
SSLClient),并把超时、代理、套接字选项等配置复制过去; - 敏感头不跨主机传递:跨主机跳转时会移除
Host、Proxy-Authorization、Authorization、Cookie、Cookie2等头部(见 httplib.h),避免把身份凭据泄露给第三方主机,这与 RFC 9110 对凭据转发的约束一致; - 跳转次数上限:请求内部维护
redirect_count_计数,超限时返回Error::ExceedRedirectCount,防止无限重定向死循环。
测试套件对重定向的覆盖相当完整(见 test/test.cc):包括/absolute-redirect/3(绝对路径跳转)、/redirect/3(相对路径跳转)、/relative-redirect/3、/redirect/21(多次跳转)以及 httpbin 风格的/redirect-to,均配合set_follow_location(true)验证最终响应状态码与 body。
错误处理与排查
HTTPS 请求失败的原因比明文 HTTP 更多:连接失败、TLS 握手失败、证书验证失败等。与普通请求一样,务必先判断返回值再使用:
httplib::Client cli("https://invalid.example.com"); auto res = cli.Get("/"); if (!res) { // 连接或 TLS 层错误 std::cout << "Error: " << httplib::to_string(res.error()) << std::endl; return 1; }res.error()返回错误枚举,httplib::to_string()可转换为可读文本。若在 OpenSSL 后端下需要进一步查看底层错误码,example/client.cc 展示了使用res.ssl_backend_error()的方式,对排查证书链不完整、协议版本不匹配等问题很有帮助。
下一步
至此你已经掌握了 HTTPS 客户端的完整用法:协议切换、端口指定、CA 证书管理与验证开关、重定向追踪,以及对应的 curl 对照命令和源码级行为依据。接下来可以尝试搭建自己的 HTTPS 服务端——从生成自签名证书开始,参见 07-https-server。
- 后端
- 网络
【免费下载链接】cpp-httplib
A C++ header-only HTTP/HTTPS server and client library
相关推荐
Podman 容器伪终端详解:--tty / -t 参数的语义、实现与实战注意事项
Podman 容器伪终端详解: tty / t 参数的语义、实现与实战注意事项 本篇指南围绕 Podman 的 tty (短选项 t )参数展开,系统讲解该参数
后端网络Grafana Tempo Kubernetes 部署验证实战:使用测试应用写入并查询追踪数据
Grafana Tempo Kubernetes 部署验证实战:使用测试应用写入并查询追踪数据 导读 本文基于 Grafana Tempo 官方文档 Valid
后端网络cpp-httplib TLS 配置实战:从 OpenSSL 安装、编译宏到 HTTPS 连接验证
cpp httplib TLS 配置实战:从 OpenSSL 安装、编译宏到 HTTPS 连接验证 HTTP 明文传输在真实环境中早已是少数派,启用 TLS 是
后端网络
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考