news 2026/10/2 1:58:53

cpp-httplib 进阶功能速览:从 Streaming、SSE 到认证、压缩与中间件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cpp-httplib 进阶功能速览:从 Streaming、SSE 到认证、压缩与中间件
  • 后端
  • 网络

【免费下载链接】cpp-httplib

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

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

恭喜你完成了 cpp-httplib Tour 全部章节的学习!你已经掌握了httplib::Client与httplib::Server的基本用法、路由、静态文件与 TLS/HTTPS 配置。本篇将系统性地介绍 Tour 中未覆盖的进阶特性:流式 API、Server-Sent Events、认证、压缩、代理、超时、Keep-Alive、中间件、日志与 Unix Domain Socket,帮助你把这些能力直接运用到 LLM 流式响应、大文件上传下载、实时推送和同机进程通信等实战场景中。读完本篇,你将能够在 cpp-httplib 项目中独立实现分块处理、自动重连的 SSE 客户端、带认证与压缩的 HTTPS 服务等完整方案。

流式 API:分块处理响应与请求

无论是处理 LLM 流式生成响应,还是下载大文件,把整个响应一次性加载进内存都是不可接受的。cpp-httplib 提供独立的stream命名空间(定义于 httplib.h),让你按块(chunk)读取数据。

客户端:stream::Get逐块消费

httplib::Client cli("http://localhost:11434"); auto result = httplib::stream::Get(cli, "/api/generate"); if (result) { while (result.next()) { std::cout.write(result.data(), result.size()); } }

stream::Result对象(httplib.h)封装了流式句柄,除next()/data()/size()外,还提供:

  • is_valid()/operator bool():判断响应是否有效;
  • status()、headers()、get_header_value():读取响应状态码与响应头;
  • error()/read_error()/has_read_error():区分连接错误与读取过程中的错误;
  • read_all():在需要时仍可一次性读完整响应。

stream::Get支持多个重载,可携带Headers、Params,并可通过最后一个参数指定chunk_size(默认 8192 字节)。除 GET 外,stream::Post、stream::Put、stream::Patch、stream::Delete、stream::Head、stream::Options同样可用(httplib.h),覆盖各类带请求体的流式场景。

客户端:content_receiver回调

也可以把回调直接传给Get(),该方式配合 Keep-Alive 使用效果更佳:

httplib::Client cli("http://localhost:8080"); cli.Get("/stream", [](const char *data, size_t len) { std::cout.write(data, len); return true; // 返回 false 可提前终止接收 });

服务端:两种内容提供者

服务端通过Response::set_content_provider()与Response::set_chunked_content_provider()(httplib.h)支持流式响应。两者的选择原则是:知道内容总长度用前者(设置Content-Length),不知道长度用后者(使用 Chunked Transfer Encoding)。

// 已知大小:设置 Content-Length svr.Get("/file", [](const auto &, auto &res) { auto size = get_file_size("large.bin"); res.set_content_provider(size, "application/octet-stream", [](size_t offset, size_t length, httplib::DataSink &sink) { // 发送从 'offset' 开始的 'length' 字节 return true; }); }); // 未知大小:Chunked Transfer Encoding svr.Get("/stream", [](const auto &, auto &res) { res.set_chunked_content_provider("text/plain", [](size_t offset, httplib::DataSink &sink) { sink.write("chunk\n", 6); return true; // 返回 false 表示发送完成 }); });

ContentProvider的本质是std::function<bool(size_t offset, size_t length, DataSink &sink)>(httplib.h),DataSink还支持sink.done()、sink.is_writable()以及写入 trailer 头。两个方法都可附带可选的ContentProviderResourceReleaser回调,在流式传输结束或出错时释放资源。

大文件上传:make_file_provider

上传大文件时,make_file_provider()(httplib.h)按 8192 字节缓冲区流式读取文件,而不是把整个文件载入内存:

httplib::Client cli("http://localhost:8080"); auto res = cli.Post("/upload", {}, {}, { httplib::make_file_provider("file", "/path/to/large-file.zip") });

该函数返回FormDataProvider,支持可选的filename与content_type参数;其底层 provider 从指定offset继续读取文件直到 EOF 并调用sink.done(),天然适配断点续传式的分块上传。更完整的文件上传方案可参考 Cookbook 中的 c07-multipart-upload 与 c09-chunked-upload。

Server-Sent Events:带自动重连的 SSE 客户端

cpp-httplib 提供了开箱即用的 SSE 客户端httplib::sse::SSEClient(httplib.h),支持基于Last-Event-ID的自动重连与断点续传:

httplib::Client cli("http://localhost:8080"); httplib::sse::SSEClient sse(cli, "/events"); sse.on_message([](const httplib::sse::SSEMessage &msg) { std::cout << msg.event << ": " << msg.data << std::endl; }); sse.start(); // 阻塞运行,内部自动重连

SSEMessage(httplib.h)包含event(事件类型,默认"message")、data(事件载荷)和id(用于Last-Event-ID头)。除了on_message全局回调,还可以为每种事件类型单独注册处理器:

sse.on_event("update", [](const httplib::sse::SSEMessage &msg) { // 仅处理 "update" 事件 });

SSEClient 还提供一套完整的事件循环控制 API:

  • on_open(OpenHandler)/on_error(ErrorHandler):连接建立与出错回调;
  • set_reconnect_interval(int ms):重连间隔,默认 3000ms;
  • set_max_reconnect_attempts(int n):最大重连次数,默认 0 表示无限重连;
  • is_connected()/last_event_id():查询连接状态与当前事件 ID;
  • start():阻塞式运行;start_async():后台线程非阻塞运行;stop():线程安全地停止;
  • set_headers(...):线程安全地更新请求头。

服务端的 SSE 实现可参考 README-sse.md 以及 Cookbook 中的 e01-sse-server、e02-sse-event-names、e03-sse-reconnect 与 e04-sse-client。

认证:Basic / Bearer Token / Digest

客户端内置了三种常用认证方式的助手方法:

httplib::Client cli("https://api.example.com"); cli.set_basic_auth("user", "password"); cli.set_bearer_token_auth("my-token");
  • set_basic_auth():在请求头写入Authorization: Basic base64(user:pass);
  • set_bearer_token_auth():写入Authorization: Bearer <token>;
  • Digest 认证:通过set_digest_auth()使用,适用于需要摘要式质询-响应流程的服务端。

服务端侧对应的验证与转发技巧可参考 Cookbook 的 c05-basic-auth 与 c06-bearer-token。

压缩:gzip / Brotli / Zstandard

cpp-httplib 支持 gzip、Brotli 与 Zstandard 三种压缩/解压算法,编译时通过宏启用,对应关系如下:

| 算法 | 编译宏 | | -- | -- | | gzip |CPPHTTPLIB_ZLIB_SUPPORT| | Brotli |CPPHTTPLIB_BROTLI_SUPPORT| | Zstandard |CPPHTTPLIB_ZSTD_SUPPORT|

客户端使用方法:

httplib::Client cli("https://example.com"); cli.set_compress(true); // 压缩请求体 cli.set_decompress(true); // 解压响应体

其中 gzip 依赖 zlib(CPPHTTPLIB_ZLIB_SUPPORT),Brotli 与 Zstandard 分别依赖对应的官方库;cmake 构建时可通过cmake/FindBrotli.cmake等模块自动探测依赖。更多细节见 Cookbook 的 c15-compression。

代理:HTTP 代理连接

客户端可以经由 HTTP 代理访问目标服务器:

httplib::Client cli("https://example.com"); cli.set_proxy("proxy.example.com", 8080); cli.set_proxy_basic_auth("user", "password");

set_proxy()指定代理主机与端口,set_proxy_basic_auth()提供代理的 Basic 认证凭据。仓库的 test/proxy 目录提供了基于 squid 的完整代理测试环境(docker-compose.yml、basic_squid.conf),test_proxy.cc 给出了可复现的验证代码;Cookbook 的 c16-proxy 有更详细讲解。

超时:连接 / 读 / 写独立配置

客户端可以分别设置连接、读、写超时:

httplib::Client cli("https://example.com"); cli.set_connection_timeout(5, 0); // 5 秒 cli.set_read_timeout(10, 0); // 10 秒 cli.set_write_timeout(10, 0); // 10 秒

每个方法接收(秒, 微秒)两个参数。此外还可通过set_read_timeout配合流式读取实现超时后的断线处理;超时相关的错误码与处理方式详见 Cookbook 的 c12-timeouts、c13-max-timeout 与 c17-error-codes。

Keep-Alive:复用 TCP 连接

对同一服务器发起多次请求时,开启 Keep-Alive 复用 TCP 连接,避免反复握手:

httplib::Client cli("https://example.com"); cli.set_keep_alive(true);

Keep-Alive 下连接可跨多个请求复用,配合前文content_receiver回调的流式读取效果最佳。详细说明见 c14-keep-alive。

服务端中间件:预处理、后处理与异常处理

pre-routing 与 post-routing 钩子

你可以在路由处理前后插入自定义逻辑:

svr.set_pre_routing_handler([](const auto &req, auto &res) { // 在每个请求处理前执行 return httplib::Server::HandlerResponse::Unhandled; // 继续正常路由 }); svr.set_post_routing_handler([](const auto &req, auto &res) { // 响应发送后执行 res.set_header("X-Server", "cpp-httplib"); });

set_pre_routing_handler返回HandlerResponse枚举:Unhandled表示继续常规路由,Handled表示由中间件直接终结本次请求(此时 res 已被中间件填好)。set_post_routing_handler在响应发出后运行,适合统一追加响应头。两者更深入的用法见 Cookbook 的 s09-pre-routing 与 s10-post-routing。

通过res.user_data在中间件与处理器间传数据

Response::user_data(httplib.h)是预路由/预请求处理器写入、路由处理器读取的任意数据容器,非常适合共享解析后的认证令牌等上下文:

svr.set_pre_routing_handler([](const auto &req, auto &res) { res.user_data.set("auth_user", std::string("alice")); return httplib::Server::HandlerResponse::Unhandled; }); svr.Get("/me", [](const auto &req, auto &res) { auto *user = res.user_data.get<std::string>("auth_user"); res.set_content("Hello, " + *user, "text/plain"); });

注意set_pre_request_handler与之的区别:它在路由匹配之前运行,连 WebSocket 路由也适用(见 s11-pre-request 与 s12-user-data)。

自定义错误与异常处理器

svr.set_error_handler([](const auto &req, auto &res) { res.set_content("Custom Error Page", "text/html"); }); svr.set_exception_handler([](const auto &req, auto &res, std::exception_ptr ep) { res.status = 500; res.set_content("Internal Server Error", "text/plain"); });

set_error_handler接管所有错误响应(404、405 等)的默认输出;set_exception_handler捕获处理器中抛出的异常并统一转换为 500 响应。两者详见 s13-error-handler 与 s14-exception-handler。

日志:服务端与客户端均可设置

服务端通过set_logger记录每个请求的方法、路径与状态码:

svr.set_logger([](const auto &req, const auto &res) { std::cout << req.method << " " << req.path << " " << res.status << std::endl; });

req中还包含remote_addr、header等信息可供记录。客户端同样支持set_logger,详见 s15-server-logger 与 c19-client-logger。

Unix Domain Socket:同机进程通信

除 TCP 外,cpp-httplib 还支持 Unix Domain Socket,适合同机进程间通信(IPC):

// 服务端 httplib::Server svr; svr.set_address_family(AF_UNIX); svr.listen("/tmp/httplib.sock", 0);
// 客户端 httplib::Client cli("http://localhost"); cli.set_address_family(AF_UNIX); cli.set_hostname_addr_map({{"localhost", "/tmp/httplib.sock"}}); auto res = cli.Get("/");

服务端把地址族设为AF_UNIX并在套接字路径上监听;客户端同样设置AF_UNIX,再通过set_hostname_addr_map把localhost映射到套接字路径,从而让常规的 URL 写法生效。完整示例见 Cookbook 的 s22-unix-socket。

继续深入:官方资源与专题文档

Tour 到此结束,但 cpp-httplib 的探索才刚刚开始。下面这些资源可以帮助你继续深入:

  • Cookbook —— 面向常见场景的配方集合,本篇提到的每个特性在 cookbook 中都有对应的分步讲解(路径参数、JSON、静态文件、TLS、WebSocket、SSE、流式响应等);
  • README.md —— 完整 API 参考手册;
  • README-sse.md —— SSE 的使用指南;
  • README-stream.md —— Streaming API 的使用指南;
  • README-websocket.md —— WebSocket 服务端与客户端的使用指南。

仓库中还提供了大量可直接运行的示例与测试:example/目录下有server.cc、client.cc、ssecli.cc、ssesvr.cc、wsecho.cc、upload.cc等完整程序,test/test.cc覆盖了上述绝大多数特性的单元测试,docs-src/pages/en/llm-app/则展示了如何用 cpp-httplib 搭建 LLM 应用的 REST API 与 SSE 流式接口。把这些代码与本文的功能速览对照阅读,你就能快速把 cpp-httplib 的进阶能力落地到自己的项目中。

  • 后端
  • 网络

【免费下载链接】cpp-httplib

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

项目地址:https://gitcode.com/GitHub_Trending/cp/cpp-httplib
点击查看免费下载
上一篇:GitHub Copilot SDK安全最佳实践:认证、授权和数据保护
下一篇:终极开源电商系统:异次元店铺完整解决方案

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

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

前端精读周刊:可视化搭建的第一步——如何抽象出统一的逻辑层

文档技术博客教程 【免费下载链接】weekly 前端精读周刊。帮你理解最前沿、实用的技术。 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/we/weekly 点击查看 免费下载 导读&#xff1a;本文是"前端精读周刊"可视化搭建系列的开篇之作&#xff0c;聚焦&…

作者头像 李华
网站建设 2026/10/2 1:57:38

CS-Base 图解系统:操作系统高效学习路线与四大模块实战指南

文档教程知识库 【免费下载链接】CS-Base 图解计算机网络、操作系统、计算机组成、数据库&#xff0c;共 1000 张图 50 万字&#xff0c;破除晦涩难懂的计算机基础知识&#xff0c;让天下没有难懂的八股文&#xff01;&#x1f680; 在线阅读&#xff1a;https://xiaolincodin…

作者头像 李华
网站建设 2026/10/2 1:56:16

LSTM电力负荷预测实践:基于PyTorch的源码拆解与避坑指南

简介&#xff1a;基于PyTorch实现的LSTM电力负荷预测完整工程&#xff0c;面向具备一定Python基础、希望入门时序预测或深度学习建模的开发者。项目覆盖数据预处理、LSTM网络搭建、训练、测试与结果可视化全流程&#xff0c;可帮助读者理解门控机制如何缓解传统RNN的梯度消失问…

作者头像 李华