使用 C/C++ 调用 libcurl 调试消息

        在使用 C/C++ 调用 libcurl 进行 HTTP 请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试。libcurl 提供了多种方法来捕获和输出这些信息,本文介绍具体的使用方式。


1. libcurl 调试工具简介

  libcurl 是一个功能强大的库,用于在 C/C++ 中实现 HTTP 请求(支持 GET、POST、PUT 等方法)。为了调试请求和响应信息,libcurl 提供了以下功能:

  • 启用详细日志输出: 使用 CURLOPT_VERBOSE 打印所有传输信息。
  • 自定义调试回调函数: 使用 CURLOPT_DEBUGFUNCTION 捕获并处理调试日志。
  • 输出请求头和请求体: 使用 CURLINFO_HEADER_OUTCURLOPT_POSTFIELDS 输出完整的请求。
  • 捕获响应内容: 使用 CURLOPT_WRITEFUNCTION 将服务器响应保存到变量中。

2. 输出请求消息

  • 使用 CURLOPT_VERBOSE

CURLOPT_VERBOSE 是最简单的调试工具,通过设置该选项为 1L,可以让 libcurl 输出详细的传输信息,包括请求头和请求体:

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

输出内容示例如下:

> POST /api HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Content-Length: 29
>
* upload completely sent off: 29 out of 29 bytes
  • 使用 CURLOPT_DEBUGFUNCTION

        如果需要对调试信息进行更多控制,可以使用 CURLOPT_DEBUGFUNCTION 自定义处理逻辑,例如将日志保存到文件或字符串中。

以下是自定义调试回调函数的代码:

#include <iostream>
#include <string>
#include <curl/curl.h>int DebugCallback(CURL* handle, curl_infotype type, char* data, size_t size, void* userptr) {std::string* log = static_cast<std::string*>(userptr);if (type == CURLINFO_HEADER_OUT) {log->append("[REQUEST HEADERS]:\n");log->append(data, size);} else if (type == CURLINFO_DATA_OUT) {log->append("[REQUEST BODY]:\n");log->append(data, size);}return 0;
}

3. 输出响应消息

为了捕获服务器的响应,可以使用 CURLOPT_WRITEFUNCTION 将响应保存到变量中:

size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {size_t totalSize = size * nmemb;userp->append((char*)contents, totalSize);return totalSize;
}

在配置 CURL 选项时,添加:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);

4. 完整代码示例

以下是一个完整的示例,展示如何使用 libcurl 发送 HTTPS POST 请求,并输出请求和响应的详细信息。

#include <iostream>
#include <string>
#include <curl/curl.h>// 自定义调试回调函数
int DebugCallback(CURL* handle, curl_infotype type, char* data, size_t size, void* userptr) {std::string* log = static_cast<std::string*>(userptr);if (type == CURLINFO_HEADER_OUT) {log->append("[REQUEST HEADERS]:\n");log->append(data, size);} else if (type == CURLINFO_DATA_OUT) {log->append("[REQUEST BODY]:\n");log->append(data, size);}return 0;
}// 回调函数:接收服务器的响应数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {size_t totalSize = size * nmemb;userp->append((char*)contents, totalSize);return totalSize;
}int main() {CURL* curl = curl_easy_init();if (!curl) {std::cerr << "Failed to initialize CURL!" << std::endl;return 1;}const std::string url = "https://example.com/api";const std::string jsonData = R"({"key1":"value1", "key2":"value2"})";std::string responseString;std::string debugLog;  // 用于存储调试日志struct curl_slist* headers = nullptr;headers = curl_slist_append(headers, "Content-Type: application/json");// 设置 CURL 选项curl_easy_setopt(curl, CURLOPT_URL, url.c_str());curl_easy_setopt(curl, CURLOPT_POST, 1L);curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);// 启用调试功能curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, DebugCallback);curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &debugLog);// 执行请求CURLcode res = curl_easy_perform(curl);if (res != CURLE_OK) {std::cerr << "CURL error: " << curl_easy_strerror(res) << std::endl;} else {std::cout << "Response: " << responseString << std::endl;}// 输出调试日志std::cout << "\n===== Debug Log =====\n" << debugLog << std::endl;curl_easy_cleanup(curl);curl_slist_free_all(headers);return 0;
}

5. 编译和运行

  • 确保已安装 libcurl。 在 Ubuntu 上安装:

    sudo apt-get install libcurl4-openssl-dev
    
  • 使用以下命令编译代码:

    g++ -o post_debug post_debug.cpp -lcurl
    
  • 运行程序:

    ./post_debug
    

6. 输出示例

程序运行后,会输出请求和响应信息,例如:

调试日志

===== Debug Log =====
[REQUEST HEADERS]:
POST /api HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 29[REQUEST BODY]:
{"key1":"value1", "key2":"value2"}

响应内容

Response: {"status":"success","message":"Data received"}

总结

通过启用 CURLOPT_VERBOSE 或自定义 CURLOPT_DEBUGFUNCTION,可以轻松查看 libcurl 的请求消息(包括请求头和请求体)。结合响应回调函数,能完整调试 HTTP 请求和服务器返回的内容。这些工具对于开发和调试网络程序非常有用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8877.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧园区系统分类及其在提升企业管理效率中的创新应用探讨

内容概要 智慧园区的概念已经逐渐深入人心&#xff0c;成为现代城市发展中不可或缺的一部分。随着信息技术的飞速发展和数字化转型的不断推进&#xff0c;一系列智慧园区管理系统应运而生。这些系统不仅帮助企业提高了管理效率&#xff0c;还在多个方面激发了创新。 首先&…

图片上传实现图片预览的功能

文章目录 图片上传实现图片预览的功能一、引言二、拖拽上传实现预览1、HTML结构与样式2、JavaScript实现拖拽逻辑 三、选择文件上传实现预览1、HTML结构2、JavaScript实现预览逻辑 四、使用示例五、总结 图片上传实现图片预览的功能 一、引言 在现代网页设计中&#xff0c;图片…

电力晶体管(GTR)全控性器件

电力晶体管&#xff08;Giant Transistor&#xff0c;GTR&#xff09;是一种全控性器件&#xff0c;以下是关于它的详细介绍&#xff1a;&#xff08;模电普通晶体管三极管进行对比学习&#xff09; 基本概念 GTR是一种耐高电压、大电流的双极结型晶体管&#xff08;BJT&am…

Linux - 进程间通信(2)

目录 2、进程池 1&#xff09;理解进程池 2&#xff09;进程池的实现 整体框架&#xff1a; a. 加载任务 b. 先描述&#xff0c;再组织 I. 先描述 II. 再组织 c. 创建信道和子进程 d. 通过channel控制子进程 e. 回收管道和子进程 问题1&#xff1a; 解答1&#xff…

【阅读笔记】New Edge Diected Interpolation,NEDI算法,待续

一、概述 由Li等提出的新的边缘指导插值(New Edge—Di-ected Interpolation&#xff0c;NEDI)算法是一种具有良好边缘保持效果的新算法&#xff0c;它利用低分辨率图像与高分辨率图像的局部协方差问的几何对偶性来对高分辨率图像进行自适应插值。 2001年Xin Li和M.T. Orchard…

Windows安装Miniconda和PySide6以及配置PyCharm

目录 1. 选择Miniconda 2. 下载Miniconda 3. 安装Miniconda 4. 在base环境下创建pyside6环境 5. 安装pyside6环境 6. 配置PyCharm环境 7. 运行第一个程序效果 1. 选择Miniconda 选择Miniconda而没有选择Anaconda&#xff0c;是因为它是一个更小的Anaconda发行版&#x…

Linux之内存管理前世今生(一)

一个程序&#xff08;如王者荣耀&#xff09;平常是存储在硬盘上的&#xff0c;运行时才把这个程序载入内存&#xff0c;CPU才能执行。 问题&#xff1a; 这个程序载入内存的哪个位置呢&#xff1f;载入内核所在的空间吗&#xff1f;系统直接挂了。 一、虚拟内存 1.1 内存分…

Java基于SSM框架的互助学习平台小程序【附源码、文档】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

【Rust自学】16.3. 共享状态的并发

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 16.3.1. 使用共享来实现并发 还记得Go语言有一句名言是这么说的&#xff1a;Do not commun…

Python 数据分析 - Matplotlib 绘图

Python 数据分析 - Matplotlib 绘图 简介绘图折线图单线多线子图 散点图直方图条形图纵置横置多条 饼图 简介 Matplotlib 是 Python 提供的一个绘图库&#xff0c;通过该库我们可以很容易的绘制出折线图、直方图、散点图、饼图等丰富的统计图&#xff0c;安装使用 pip install…

Java进阶(二):Java设计模式

目录 设计模式 一.建模语言 二.类之间的关系 1.依赖关系 2.关联关系 3.聚合关系 4.组合关系 5.继承关系 6.实现关系 三.面向对象设计原则 单一职责原则 开闭原则 里氏替换原则 依赖倒置 接口隔离原则 迪米特原则 组合/聚合(关联关系)复用原则 四.23种设计模式…

双层Git管理项目,github托管显示正常

双层Git管理项目&#xff0c;github托管显示正常 背景 在写React项目时&#xff0c;使用Next.js,该项目默认由git托管。但是我有在项目代码外层记笔记的习惯&#xff0c;我就在外层使用了git托管。 目录如下 code 层内也有.git 文件&#xff0c;对其托管。 我没太在意&…

群晖docker获取私有化镜像http: server gave HTTP response to HTTPS client].

群晖docker获取私有化镜像提示http: server gave HTTP response to HTTPS clien 问题描述 层级时间用户事件Information2023/07/08 12:47:45cxlogeAdd image from xx.xx.31.240:1923/go-gitea/gitea:1.19.3Error2023/07/08 12:47:48cxlogeFailed to pull image [Get "http…

机器学习:支持向量机

支持向量机&#xff08;Support Vector Machine&#xff09;是一种二类分类模型&#xff0c;其基本模型定义为特征空间上的间隔最大的广义线性分类器&#xff0c;其学习策略便是间隔最大化&#xff0c;最终可转化为一个凸二次规划问题的求解。 假设两类数据可以被 H x : w T x…

相互作用感知的蛋白-小分子对接模型 - Interformer 评测

Interformer 是一个应用于分子对接和亲和力预测的深度学习模型&#xff0c;基于 Graph-Transdormer 架构的模型&#xff0c;利用相互作用&#xff08;氢键、疏水&#xff09;感知的混合密度网络&#xff08;interaction-aware mixture den sity network&#xff0c; MDN&#x…

如果我想设计一款复古风格的壁纸,应该选什么颜色?

设计复古风格的壁纸时&#xff0c;选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议&#xff1a; 一、复古风格的主色调 棕色系&#xff1a; 特点&#xff1a;棕色是复古风格的…

AI 浪潮席卷中国年,开启科技新春新纪元

在这博主提前祝大家蛇年快乐呀&#xff01;&#xff01;&#xff01; 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其影响力已经渗透到社会生活的方方面面。在中国传统节日 —— 春节期间&#xff0c;AI 技术也展现出了巨大的潜力&#xff0c;为中国年带…

WPS数据分析000007

目录 一、分列 智能分列 出生日期 数值转换 公式不运算 二、数据对比 离职员工 新入职员工 都在职的员工 三、合并计算 四、拆分表格 合并表格 一、分列 智能分列 出生日期 数据求和 文本型数字左对齐&#xff1b;数值型数字右对齐 数值转换 方式一&#xff1a; 方…

fps一些内容添加

1 增强输入要点记录 输入 &#xff1a;输入值的类型 布尔 1d&#xff0c;2d&#xff0c;3d 映射&#xff1a;就是确定按键输入键位&#xff0c;输入类型&#xff0c;和一些触发器&#xff08;按键方式&#xff09;修改器&#xff08;对输出值进行修改&#xff09; 基本的&am…

深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用

title: 深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用 date: 2025/1/26 updated: 2025/1/26 author: cmdragon excerpt: 在现代数据库管理系统中,索引技术是提高查询性能的重要手段。当数据量不断增长时,如何快速、有效地访问这些数据成为了数据库设计的核…