news 2026/10/3 16:48:52

cpp-httplib Cookbook 完全指南:从客户端到服务端、TLS、SSE 与 WebSocket 的 52 个实战配方

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cpp-httplib Cookbook 完全指南:从客户端到服务端、TLS、SSE 与 WebSocket 的 52 个实战配方
  • 后端
  • 网络

【免费下载链接】cpp-httplib

A C++ header-only HTTP/HTTPS server and client library

项目地址:https://gitcode.com/GitHub_Trending/cp/cpp-httplib
点击查看免费下载

导读

本文基于 cpp-httplib 官方文档的 Cookbook 索引页(docs-src/pages/ja/cookbook/index.md),系统梳理了该项目面向实战的全部「怎么做?」(How do I...?)配方:客户端(C01–C19)、服务器(S01–S23)、TLS/安全(T01–T05)、SSE(E01–E04)与 WebSocket(W01–W06)五大板块。每个配方相互独立,可单独查阅;读完本文,你将掌握 cpp-httplib 在鉴权、文件上传、流式传输、连接管理、错误处理、协议扩展等场景下的标准解法,并能直接定位到对应源码与示例。

关于基础用法的入门介绍,请参阅 Tour 教程。


一、Cookbook 的整体结构:如何按需检索

Cookbook 的设计原则是「每个配方自包含(self-contained),只读你需要的页面」。它按主题划分为五个大区,每个大区下再按用途细分:

板块编号范围覆盖主题篇数
客户端(Client)C01–C19响应获取、JSON、鉴权、文件上传、流式传输、连接性能、错误处理19
服务器(Server)S01–S23路由注册、JSON API、静态文件、流式响应、处理器链、运维调优、协议扩展23
TLS / 安全T01–T05TLS 后端选型、证书校验、SSL 服务器、mTLS、对端证书5
SSEE01–E04SSE 服务器、事件名、重连、客户端接收4
WebSocketW01–W06回显服务器、心跳、关闭、二进制帧、TLS、超时6

这种编号体系本身就是一张「问题 → 解法」的映射表:例如你想知道「如何给客户端设置超时」,直接找 C12;想了解「如何在服务端实现优雅停机」,直接看 S19。下文按板块展开,并对每个配方给出核心思路与源码佐证。


二、客户端配方(C01–C19)

2.1 基本操作(C01–C04)

C01:获取响应体 / 保存到文件(c01-get-response-body.md)

  • 以字符串获取:res->body是std::string,可直接使用,但整个响应会被加载进内存:
httplib::Client cli("http://localhost:8080"); auto res = cli.Get("/hello"); if (res && res->status == 200) { std::cout << res->body << std::endl; }
  • 大文件应改用ContentReceiver逐块接收并直接写入文件,避免内存占用:
std::ofstream ofs("output.bin", std::ios::binary); auto res = cli.Get("/large-file", & { ofs.write(data, len); return static_cast<bool>(ofs); // false 则中断下载 });

回调返回false即可中止下载;若需在下载前查看Content-Length等头部,可组合ResponseHandler(在收到头部后、读取正文前被调用,返回false可跳过整个下载)。下载进度则参见 C11。

C02:收发 JSON(c02-json.md)

cpp-httplib 自身不含 JSON 解析器,需配合 nlohmann/json 等库:

nlohmann::json j = {{"name", "Alice"}, {"age", 30}}; auto res = cli.Post("/api/users", j.dump(), "application/json");

发送时第 2 参数为 JSON 字符串、第 3 参数为 Content-Type,Put()/Patch()同构;接收时直接nlohmann::json::parse(res->body)。注意:Content-Type 必须显式指定"application/json",否则服务端可能不按 JSON 处理;解析前应先检查状态码,防止服务端错误时返回 HTML 导致解析异常。

C03:设置默认头(c03-default-headers.md)

set_default_headers()一次性登记所有请求共用的头部(如Accept、User-Agent、Authorization):

cli.set_default_headers({ {"Accept", "application/json"}, {"User-Agent", "my-app/1.0"}, });

从源码看,该方法对应 httplib.h 中ClientImpl的default_headers_成员,调用即整体覆写该集合(见 ClientImpl::set_default_headers),因此追加单个头时也需传回完整集合。请求级通过Headers传入的头会与默认头合并发送,二者可叠加使用。

C04:跟随重定向(c04-follow-location.md)

cpp-httplib 默认不跟随3xx 重定向,302会原样返回;调用cli.set_follow_location(true)后,客户端会依据Location头自动重发请求:

httplib::Client cli("http://example.com"); cli.set_follow_location(true); auto res = cli.Get("/old-path"); // 最终响应进入 res

该方法在源码中对应follow_location_标志位(ClientImpl::set_follow_location),并支持跨 scheme/host 跳转(如 HTTP→HTTPS)。前提是库已以 OpenSSL 或其他 TLS 后端编译,否则无法跟随到 HTTPS。跟随重定向会拉长请求耗时,超时设置参考 C12。

2.2 认证(C05–C06)

C05:Basic 认证(c05-basic-auth.md)

set_basic_auth("alice", "s3cret")让库自动组装Authorization: Basic ...头(对应 ClientImpl::set_basic_auth);也可用httplib::make_basic_authentication_header()生成 Base64 编码头,实现请求级认证。安全警告:Basic 仅做 Base64 编码而非加密,必须走 HTTPS。更安全的 Digest 认证用set_digest_auth(),该方法仅在以 OpenSSL 等 TLS 后端构建时可用(ClientImpl::set_digest_auth)。

C06:Bearer Token 调用 API(c06-bearer-token.md)

set_bearer_token_auth(token)自动组装Authorization: Bearer <token>(ClientImpl::set_bearer_token_auth),适合 OAuth 2.0 类 API;请求级可用make_bearer_token_authentication_header()。Token 过期后只需用新 Token 再次调用set_bearer_token_auth()即可刷新。警告:Bearer Token 本身即凭证,务必 HTTPS 传输且不要硬编码进源码。

2.3 文件上传(C07–C09)

C07:multipart/form-data 上传(c07-multipart-upload.md)

按文件大小二选一:

  • 小文件:先整体读入内存,用UploadFormDataItems,元素结构为{name, content, filename, content_type},文本字段把后两项留空:
httplib::UploadFormDataItems items = { {"name", "Alice", "", ""}, {"avatar", content, "avatar.png", "image/png"}, }; auto res = cli.Post("/upload", items);
  • 大文件:用FormDataProviderItems+make_file_provider("表单名", "文件路径", "文件名", "Content-Type")流式发送(make_file_provider),不占内存;文件名传空则用文件路径。两类 items 可在同一请求中混用——文本字段走UploadFormDataItems、文件走FormDataProviderItems是推荐做法。

C08:以原始二进制 POST 文件(c08-post-file-body.md)

用于 S3 兼容 API、原始图像上传等「正文即文件」的场景。make_file_body()返回(size, ContentProvider)对(make_file_body),可直接喂给Put()/Post():

auto [size, provider] = httplib::make_file_body("backup.tar.gz"); if (size == 0) { /* 文件打开失败 */ } auto res = cli.Put("/bucket/backup.tar.gz", size, provider, "application/gzip");

ContentProvider按块读文件,内存友好;但该 API 需预先确定 Content-Length,不适合发送过程中大小会变化的文件。

C09:Chunked 传输正文(c09-chunked-upload.md)

适用于无法预知正文总长度的场景(如实时生成的数据流),用ContentProvider配合 chunked transfer 逐块发送。

2.4 流式与进度(C10–C11)

  • C10 流式接收响应(c10-stream-response.md):通过ContentReceiver逐块处理响应,避免整包入内存。
  • C11 进度回调(c11-progress-callback.md):set_progress_callback()可同时获得上传/下载字节数,用于实现进度条,常与 C07、C08 的大文件传输配合。

2.5 连接与性能(C12–C16)

  • C12 超时设置(c12-timeouts.md):set_connection_timeout()、set_read_timeout()、set_write_timeout()分别控制建连、读、写超时。
  • C13 整体超时(c13-max-timeout.md):set_connection_timeout()之外,整体超时(overall timeout)用于约束整个请求的总时长,适合慢接口兜底。
  • C14 Keep-Alive 与连接复用(c14-keep-alive.md):理解连接池复用行为,避免反复握手;set_keep_alive_max_count()可限制单连接最大请求数。
  • C15 压缩(c15-compression.md):set_compress(true)开启 gzip 压缩,需要库以 zlib/brotli 构建(CMake 侧见 cmake/FindBrotli.cmake)。
  • C16 代理(c16-proxy.md):set_proxy(host, port)设置 HTTP 代理,项目测试目录 test/proxy 提供了基于 Squid + httpbin 的代理测试环境(docker-compose.ci.yml可用于 CI 验证)。

2.6 错误处理与调试(C17–C19)

  • C17 错误码(c17-error-codes.md):请求失败时res为nullptr,可用cli.get_last_error()/cli.get_error()获取Error枚举(连接失败、超时、TLS 错误等),据此区分失败类别。
  • C18 SSL 错误(c18-ssl-errors.md):针对证书校验失败、握手失败等 TLS 专项错误的处理套路。
  • C19 客户端日志(c19-client-logger.md):set_logger()注册日志回调,记录请求行与响应状态,便于排查。

三、服务器配方(S01–S23)

3.1 基本路由(S01–S04)

S01:注册 GET / POST / PUT / DELETE 处理器(s01-handlers.md)

处理器签名统一为(const Request&, Response&):

httplib::Server svr; svr.Get("/hello", [](const httplib::Request &req, httplib::Response &res) { res.set_content("Hello, World!", "text/plain"); }); svr.Post("/api/items", [](const httplib::Request &req, httplib::Response &res) { // req.body 即请求正文 res.status = 201; res.set_content("Created", "text/plain"); }); svr.listen("0.0.0.0", 8080); // 阻塞启动

res.set_content()设置正文与 Content-Type,res.status设置状态码。查询参数用req.get_param_value("q")(先查存在性用req.has_param()),请求头用req.get_header_value("User-Agent"),响应头用res.set_header("Name", "Value")。listen()是阻塞调用,需并行启动时见 S18。

S02:JSON 请求 / 响应(s02-json-api.md):服务端从req.body取 JSON 字符串交给 JSON 库解析,用res.set_content(j.dump(), "application/json")返回;与客户端 C02 对称。

S03:路径参数(s03-path-params.md):路由模式/users/:id中的:id可用req.path_params(或req.get_param_value系方法)取出。

S04:静态文件服务器(s04-static-files.md):svr.set_mount_point("/", "./public")将本地目录挂载为静态资源;项目测试用 test/www、test/www2、test/www3 三套目录验证挂载行为(含中文目录名、空文件等边界)。

3.2 流式与文件(S05–S08)

  • S05 流式返回大文件(s05-stream-response.md):res.set_content_provider()/set_chunked_content_provider()配合DataSink分块写出,避免大文件整体入内存。
  • S06 下载响应(s06-download-response.md):res.set_content_provider()+Content-Disposition: attachment头,让浏览器/客户端以附件形式保存。
  • S07 流式接收 multipart(s07-multipart-reader.md):MultipartFormDataMap与流式读取 API 处理上传表单,与客户端 C07 对应。
  • S08 压缩响应(s08-compress-response.md):res.set_content_provider配合set_compress在服务端开启 gzip/brotli 输出。

3.3 处理器链(S09–S12)

  • S09 全路由前置处理(s09-pre-routing.md):svr.set_pre_routing_handler()在路由分发前统一处理(如全局限流、CORS)。
  • S10 Post-routing 追加响应头(s10-post-routing.md):svr.set_post_routing_handler()在路由处理后统一附加头部。
  • S11 Pre-request 按路由鉴权(s11-pre-request.md):svr.set_pre_routing_handler()结合req.path实现路由级认证(对应客户端 C05/C06 的认证头)。
  • S12res.user_data传递数据(s12-user-data.md):处理器间通过res.user_data(std::any)共享数据,典型用于 pre-routing 注入用户信息、后续处理器消费。

3.4 错误处理与调试(S13–S16)

  • S13 自定义错误页(s13-error-handler.md):svr.set_error_handler()统一接管 4xx/5xx 的响应体与状态码。
  • S14 捕获异常(s14-exception-handler.md):svr.set_exception_handler()捕获处理器抛出的std::exception,避免连接被直接关闭。
  • S15 请求日志(s15-server-logger.md):svr.set_logger()记录每个请求的 method、path、状态码与耗时。
  • S16 检测客户端断开(s16-disconnect.md):req.is_connection_closed()判断长连接是否已断开,用于提前终止流式输出。

3.5 运维与调优(S17–S22)

  • S17 动态端口(s17-bind-any-port.md):svr.bind_to_any_port("0.0.0.0")后由svr.port()读取实际分配端口,适合测试与端口自动协商。
  • S18listen_after_bind控制启动顺序(s18-listen-after-bind.md):先bind()后listen_after_bind(),可在监听前完成端口获取、初始化等工作,也是非阻塞启动的关键。
  • S19 优雅停机(s19-graceful-shutdown.md):在另一线程调用svr.stop(),配合wait_until_ready()/is_running()实现可控关停。
  • S20 调优 Keep-Alive(s20-keep-alive.md):svr.set_keep_alive_max_count()控制单连接可处理的请求数,平衡连接复用与资源释放。
  • S21 线程池(s21-thread-pool.md):svr.new_task_queue = [] { return new httplib::ThreadPool(n, m); }指定工作线程上下限;ThreadPool实现位于 httplib.h 内部线程池部分,另有独立测试 test/test_thread_pool.cc。
  • S22 Unix domain socket(s22-unix-socket.md):svr.listen("/path/to/sock")让服务器监听 Unix socket,供同机进程间通信。

3.6 协议扩展(S23)

S23:自定义 HTTP 方法(s23-custom-methods.md):对PROPFIND等非内置方法,用svr.CustomRoute("PROPFIND", "/path", handler)注册,实现 WebDAV 等扩展协议。


四、TLS / 安全(T01–T05)

  • T01 TLS 后端选型(t01-tls-backends.md):cpp-httplib 支持 OpenSSL、mbedTLS、wolfSSL 三种后端,按平台生态、证书管理、体积等维度选择;CMake 构建配置见 cmake/modules.cmake 与顶层 CMakeLists.txt。
  • T02 证书校验控制(t02-cert-verification.md):cli.enable_server_certificate_verification(true)与cli.set_ca_cert_path()管理 CA 信任链。
  • T03 启动 SSL/TLS 服务器(t03-ssl-server.md):httplib::SSLServer svr; svr.set_cert_file(...); svr.set_key_file(...)配置证书密钥后正常注册路由。
  • T04 配置 mTLS(t04-mtls.md):set_ca_cert_file()要求客户端证书,实现双向认证;客户端侧对应set_client_cert_path()/set_client_key_path()。
  • T05 服务端读取对端证书(t05-peer-cert.md):通过SSLServer请求上下文获取对端证书信息(如 CN、SAN),用于细粒度授权。

证书生成脚本见 test/gen-certs.sh,TLS 测试覆盖于 test/test.cc。


五、SSE(E01–E04)

SSE(Server-Sent Events)是服务器向客户端单向推送的轻量协议,cpp-httplib 没有 SSE 专用 API,但用set_chunked_content_provider()+text/event-stream即可实现(e01-sse-server.md):

svr.Get("/events", [](const httplib::Request &req, httplib::Response &res) { res.set_chunked_content_provider( "text/event-stream", [](size_t offset, httplib::DataSink &sink) { std::string message = "data: hello\n\n"; // \n\n 分隔一个事件 sink.write(message.data(), message.size()); std::this_thread::sleep_for(std::chrono::seconds(1)); return true; // 返回 true 则持续推送 }); });

三个要点:Content-Type 设为text/event-stream;消息遵循data: <内容>\n\n格式(含多行内容时每行都要以data:开头);每次sink.write()客户端立即可收到。可用req.is_connection_closed()+sink.done()优雅结束推送(结合 S16),用: ping\n\n注释行做心跳防止代理断连。

配套配方:E02 事件名区分(event:字段)、E03 断线重连(retry:字段与Last-Event-ID)、E04 客户端接收(用ContentReceiver解析事件流)。仓库还提供独立 SSE 文档 README-sse.md 与示例 example/ssesvr.cc、example/ssecli.cc、example/ssecli-stream.cc 可对照学习。注意:SSE 每连接会占用一个工作线程,并发高时应将线程池设为动态伸缩(如ThreadPool(8, 128),详见 S21)。


六、WebSocket(W01–W06)

  • W01 回显服务器 / 客户端(w01-websocket-echo.md):服务端svr.Get("/ws", websocket_handler),通过req.ws的消息回调收发文本/二进制帧;示例见 example/wsecho.cc。
  • W02 心跳(w02-websocket-ping.md):ping()定时发送 Ping 帧维持连接与探活;配套独立测试 test/test_websocket_heartbeat.cc。
  • W03 关闭处理(w03-websocket-close.md):在 close 回调中清理资源,处理对端主动关闭。
  • W04 二进制帧(w04-websocket-binary.md):区分文本/二进制帧类型,收发任意字节序列。
  • W05 wss:// 的 TLS(w05-websocket-tls.md):SSLServer+ WebSocket 路由即得 wss 服务端;客户端用httplib::Client走 https 地址。
  • W06 超时设置(w06-websocket-timeouts.md):配置读写超时避免僵尸连接;线程安全相关验证见 test/test_websocket_thread_safety.cc,综合文档见 README-websocket.md。

七、如何把 Cookbook 落到代码中

  1. 引入库:cpp-httplib 是 header-only 库,只需#include "httplib.h"(仓库根目录 httplib.h,约 1.9 万行),并链接系统网络库;如需 TLS 则按 T01 选择后端编译。构建示例可参考 example/Makefile 与 CMakeLists.txt。
  2. 按需取配方:从本文的编号映射定位问题,直接打开对应文档,每个配方都是可独立编译的最小示例;想系统入门先读 Tour 的 01–09 章。
  3. 对照示例与测试:客户端/服务器综合示例见 example/server.cc、example/client.cc、example/server_and_client.cc(同一进程双端通信);行为验证覆盖于 test/test.cc,SSE 见 README-sse.md,流式传输见 README-stream.md。
  4. 适用前提:文中 TLS、Digest 认证、压缩等能力依赖编译期开启的对应后端(OpenSSL/mbedTLS/wolfSSL、zlib/brotli),未开启时相关 API 不可用或行为受限,请以当前构建配置为准。
  • 后端
  • 网络

【免费下载链接】cpp-httplib

A C++ header-only HTTP/HTTPS server and client library

项目地址:https://gitcode.com/GitHub_Trending/cp/cpp-httplib
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 16:48:33

【大数据毕设推荐】K-Means与FP-Growth算法实战:电动汽车品牌与车型流行趋势数据分析系统源码解析 毕业设计 选题推荐 毕设选题 数据分析 机器学习

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡如果你遇到具体的…

作者头像 李华
网站建设 2026/10/3 16:46:18

2026年AI动漫短剧制作完整教程:从剧本到成片的8个环节与验收清单

本文回答&#xff1a;AI 动漫短剧从剧本到成片要过哪 8 个环节&#xff0c;每个环节产出什么、按什么验收&#xff0c;Seedance 2.0 与 2.5 两版提示词规范怎么分开写&#xff0c;以及自己用工具做、调接口、用 AI 视频产线、外包几种做法怎么选。 ai动漫短剧教程的核心是一条从…

作者头像 李华
网站建设 2026/10/3 16:42:58

步进电机控制方案:DRV8818PWPR与PIC24FJ128GA310的协同设计

做步进电机控制的这些年&#xff0c;我越来越觉得“芯片选型”这件事比写代码更重要。DRV8818PWPR这颗驱动芯片搭配PIC24FJ128GA310这颗 16 位单片机&#xff0c;是我在工业机器人和自动化设备项目里反复验证过的一套组合&#xff1a;一个负责把电流变成力矩&#xff0c;一个负…

作者头像 李华
网站建设 2026/10/3 16:42:52

在Mac上使用 OpenClaw 调用大模型 kimi-cloud:把 endpoint 改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 16:42:51

通义灵码Agent闭环工作流:用Quest模式打通AI文档到代码落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华