【C三方组件】cpr最像 Python requests 的 HTTP 客户端【摘要】cpr 在 libcurl 之上提供面向 C 的 HTTP 客户端接口用参数对象描述请求用 Response 接收结果。本文介绍它减少了哪些配置和资源管理代码再通过参数化 GET、JSON POST、Session、文件上传下载和异步请求说明用法。【版本基准】cpr 1.14.2MIT配套验证使用 libcurl 8.22.0C17。完整代码见 cpr_demo.cpp请求目标与第 26 篇共用本地 mock。1. Whatcpr 是什么cpr 的全称是 C Requests是一个基于 libcurl 的 HTTP 客户端库。它把 URL、超时、请求头、查询参数等配置封装成 C 类型并把状态码、响应体和传输错误组织成一个返回对象。一个请求可以写成autoresponsecpr::Get(cpr::Url{http://127.0.0.1:18080/echo},cpr::Parameters{{msg,hello cpr}},cpr::Timeout{3000});底层协议能力仍由 libcurl 提供因此 cpr 的依赖树中包含 libcurlTLS、代理及协议支持也受其构建配置影响。cpr 自身的主要价值在 C 使用接口、资源管理和常见调用方式上。2. Why已有 libcurl为什么还要一层封装直接用 libcurl 完全可行。对于应用层代码重复工作往往集中在这些地方创建和销毁 handle、设置选项、维护头链表、接收响应片段、查询状态和处理错误。工作直接使用 libcurlcpr 的表达配置 URL 与超时curl_easy_setopt与对应参数类型Url、Timeout、ConnectTimeout编码查询参数转义后拼接 URLParameters设置请求头创建并释放curl_slistHeader接收小响应写回调、接收缓冲、getinfoResponse顺序复用客户端管理 easy handle 的状态Session表单上传和文件下载配置 MIME、读写回调等Multipart、Download例如第 26 篇的 GET 需要准备 easy handle、字符串回调和清理逻辑上面的cpr::Get可以直接返回结果。比较两者时仍要保留相同的超时、错误检查和认证策略不能拿省略错误处理的“一行代码”与完整生产代码比较。自行封装 libcurl 也能获得类似体验但团队需要维护封装接口、参数转换、对象寿命和版本适配。若需求主要是常见 HTTP 调用采用已有封装可以减少这部分维护若需要深度融入自定义事件循环或控制全部底层传输行为则应确认 cpr 暴露的接口是否满足需求。3. How接入与公共错误处理vcpkg 包名为cprfind_package(cpr CONFIG REQUIRED) add_executable(app cpr_demo.cpp) target_compile_features(app PRIVATE cxx_std_17) target_link_libraries(app PRIVATE cpr::cpr)源码集成时CPR_USE_SYSTEM_CURLON表示使用系统中已有的 libcurl该选项应在配置 cpr 前设置。不要混用不兼容的编译器 ABI 或不同架构的库。配套工程选择BLOG_COMPONENTScpr;httplib。先运行./build/httplib_demo serve18080客户端头文件为cpr/cpr.h。以下案例共用一个show函数staticvoidshow(constcpr::Responseresponse){if(response.error.code!cpr::ErrorCode::OK)throwstd::runtime_error(response.error.message);std::coutstatusresponse.status_code bodyresponse.text\n;if(response.status_code200||response.status_code300)throwstd::runtime_error(HTTP request failed);}先检查传输再解释 HTTP 状态。收到 404 与 DNS 失败是两种不同情况传输在收到任何 HTTP 状态前就失败时状态码通常为 0。传输进行到一半后失败也可能已经有状态码因此判断依据应是error不能仅判断status_code 0。3.1 参数化 GET把编码交给库conststd::string basehttp://127.0.0.1:18080;show(cpr::Get(cpr::Url{base/echo},cpr::Parameters{{msg,hello cpr}},cpr::Timeout{3000},cpr::ConnectTimeout{1000}));Parameters负责查询参数编码不需要自己把空格、中文或拼到 URL 中。服务端得到的是解码后的参数值。Timeout和ConnectTimeout的整数参数以毫秒为单位。./build/cpr_demo getstatus200 bodyhello cpr请求头也通过参数对象表达例如cpr::Header{{Accept, application/json}}。需要 Basic 认证时可以使用AuthenticationBearer token 可以放入 Authorization 请求头日志中应避免输出完整凭据。3.2 POST JSON序列化与传输分工明确show(cpr::Post(cpr::Url{base/json},cpr::Body{R({msg:hello, cpr})},cpr::Header{{Content-Type,application/json}},cpr::Timeout{3000}));Body表示请求体原文cpr 不会自动把任意对象转换为 JSON。业务数据可以先用 JSON 库序列化再交给Body。表单字段则可以使用Payload两者的编码与 Content-Type 不应混用。./build/cpr_demo poststatus200 body{received:hello, cpr}这个 mock 会解析 JSON 并检查msg是否为字符串。把请求体改为无效 JSON可以观察“传输成功但服务端返回 400”的路径。3.3 Session保留配置顺序复用客户端cpr::Session session;session.SetUrl(cpr::Url{base/echo});session.SetTimeout(cpr::Timeout{3000});for(constauto*value:{first,second}){session.SetParameters(cpr::Parameters{{msg,value}});show(session.Get());}./build/cpr_demo sessionstatus200 bodyfirst status200 bodysecondSession 便于保存配置与传输状态并为底层连接复用创造条件是否真正复用还取决于服务器、协议和连接状态。改变方法、请求头或参数时也要考虑上一次配置是否仍然有效。同一个可变 Session 不应同时被多个线程随意修改。并发请求使用独立状态或者采用库为相应版本提供的并发接口。3.4 Multipart上传已有文件先准备一个upload.txt内容可以是hello。然后调用show(cpr::Post(cpr::Url{base/upload},cpr::Multipart{{file,cpr::File{upload.txt}}},cpr::Timeout{3000}));./build/cpr_demo upload服务端返回接收到的字节数。字段名file是客户端与服务端的约定实际项目应按接口定义填写。multipart 的 boundary 和编码由库管理不需要把整份文件读进字符串后手工拼接。配套程序先检查本地文件能否打开文件大小、服务器限制和请求超时也应一起考虑。操作系统文本换行不同可能改变文件字节数不应硬编码一个跨平台输出值。3.5 下载把响应写入文件std::ofstreamfile(download-cpr.txt,std::ios::binary);if(!file)throwstd::runtime_error(cannot open output file);autoresponsecpr::Download(file,cpr::Url{base/download},cpr::Timeout{3000});file.close();show(response);if(!file)throwstd::runtime_error(file write failed);./build/cpr_demo download下载内容进入文件response.text不再承担保存整份文件的任务。大响应若直接用普通Get并保存在text中会增加内存占用。需要自定义消费方式时可以使用WriteCallback。1.14.2 的回调数据类型是std::string_view消费时不要把这个临时视图保存到回调之外要跨回调持有数据应复制到自己管理的存储。异步下载时文件及回调捕获的对象也必须活到操作完成。3.6 异步请求先发起再等待结果autofirstcpr::GetAsync(cpr::Url{base/hi},cpr::Timeout{3000});autosecondcpr::GetAsync(cpr::Url{base/echo},cpr::Parameters{{msg,async}},cpr::Timeout{3000});show(first.get());show(second.get());./build/cpr_demo async使用auto保存异步返回对象再通过.get()取得结果。这里先提交两次请求再等待如果每次提交后立刻.get()调用方仍会按顺序等待。异步对象的具体类型与执行实现应以所用版本为准不应把所有版本统一描述成固定的std::future或某一种线程池。异步调用也需要超时、取消和并发数量控制。发起上万个请求后同时等待不等于已经设计好了资源上限。3.7 错误路径404 与传输超时配套程序提供errors模式访问不存在的路由再用 30ms 超时访问耗时约 200ms 的/slow。./build/cpr_demo errors对应的两类结果是404: transport_ok1 status404 timeout: transport_ok0 status0这里第二行的 0 来自这个“尚未收到响应头就超时”的具体案例。程序通过符号枚举ErrorCode::OPERATION_TIMEDOUT检查原因不依赖硬编码错误数字。4. 用到项目里还要考虑什么配置统一超时和必要的响应大小限制对 HTTPS 保持身份校验并修复实际的证书配置只在明确业务语义后加入重试。下载失败时要处理部分文件上传失败也不能自动假设服务端没有收到数据。如果多个调用都需要相同的认证、日志和重试规则可以在应用层封装客户端或评估 cpr 的 Interceptor 接口。拦截器的作用范围取决于注册方式不是创建一个对象就自动影响全程序。5. 选型与参考cpr 适合希望快速编写常见 HTTP 调用的 C 应用。直接 libcurl 更适合需要底层控制的代码Boost.Beast 适合已有 Asio 基础、希望组合协议操作的程序。它们都可能用于客户端应按抽象层和运行模型比较。cpr 项目与说明功能、构建与版本信息。1.14.2 API 定义同步、异步和下载接口。1.14.2 回调定义回调参数与返回语义。完整示例七种运行模式及对应错误检查。
企业数字化 ERP 产品动态
相关推荐
CI/CD 实战:GitHub Actions 自动化构建、测试与发布流水线 摘要:本文以一条可直接复制运行的 GitHub Actions 流水线为主线,手把手教你把「代码提交 → 自动构建 → 多版本测试 → 产物发布」串成端到端的 CI/CD 自动化流程。内容覆盖 workflow 核心概念、依赖缓存、matrix 矩阵并行测试、Artifacts 跨 Job 产物传… · 2026/9/27 22:52:41
网站备案名字要怎么写源码下载 网站备案名字怎么写?用这3个免费工具搞定备案与SEO 改个需求建站公司拖一周,这种憋屈事儿谁没经历过?很多站长朋友刚把网站做出来,准备上线,结果卡在“网站备案名字怎么写”这一步,不仅流程繁琐,还怕填错被驳回。其实,备案名称填写和后续的SEO… · 2026/9/27 22:52:29
集成pageOffice到springboot项目关键步骤 集成pageOffice到springboot项目关键步骤
PageOffice(卓正软件)是国内常用的Web 在线 Office 文档编辑控件,用于 OA、政务、ERP 等 B/S 系统,在网页里直接打开、编辑、保存 Word/Excel/PPT,不需要下载上传文件… · 2026/9/27 22:52:22
LabVIEW Vision Assistant 2024保姆级入门:工业视觉开发基座构建指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:50
无路由器也能组网:Linux下Ad-hoc/IBSS无线网络搭建与排障实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:50
GD32450Z USBHS内部PHY实现USB Host读写U盘与FatFs文件系统 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:50
SLVS-EC v2.0封包结构详解:ECC与CRC校验机制及FPGA调试实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:50
400个NES游戏资源包整理指南:分类、模拟器与优化 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:43
Vivado CORDIC IP核算sin/cos三大坑:相位格式、输出定标与时序握手 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:30:43
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01