必须显式设置curlopt_postfields指向json字符串和curlopt_httpheader添加"content-type: application/json",否则服务端易返回400;需用curl_slist_append构造头列表,显式设curlopt_postfieldsize防截断,推荐nlohmann/json生成utf-8编码字符串。

curl_easy_setopt 设置 POST 数据和 Content-Type
直接用 curl_easy_setopt 传 JSON 字符串时,必须显式设置两个关键选项:一是用 CURLOPT_POSTFIELDS 指向 JSON 字符串内存,二是用 CURLOPT_HTTPHEADER 添加 Content-Type: application/json。漏掉后者,服务端大概率返回 400 或直接忽略 body。
常见错误是只设 CURLOPT_POSTFIELDS,以为 curl 会自动推断类型——它不会。JSON 字符串本身只是普通字节流,没有元信息。
-
CURLOPT_POSTFIELDS接收const char*,指向以\0结尾的 JSON 字符串(不是std::string::c_str()后立刻析构的临时对象) -
CURLOPT_POSTFIELDSIZE建议显式设置长度(比如strlen(json_str)),避免 curl 错误截断含 \0 的 JSON(虽然标准 JSON 不含 \0,但保险起见) - HTTP 头必须用
curl_slist_append构建,不能直接传字符串数组;头列表需在 easy handle 销毁前用curl_slist_free_all释放
构造 JSON 字符串别依赖手拼,优先用成熟库
手写 JSON 容易出错:引号没转义、中文乱码、嵌套结构缺逗号或括号。C++ 里推荐用 nlohmann/json 或 rapidjson 生成字符串,而不是 std::ostringstream 拼接。
例如用 nlohmann/json:
#include <nlohmann>
nlohmann::json j = {{"user_id", 123}, {"tags", {"dev", "cpp"}}};
std::string json_str = j.dump(); // 自动转义、格式化、UTF-8 编码
// 确保 json_str.data() 在 curl 请求期间有效(比如声明为局部 static 或成员变量)
</nlohmann>
注意:j.dump() 返回的是 UTF-8 字符串,如果 JSON 含中文,手拼字符串容易因源文件编码不一致导致乱码。
POST 请求后检查 HTTP 状态码和错误码,别只看返回值是否为 CURLE_OK
curl_easy_perform 返回 CURLE_OK 只代表网络传输成功,不代表 HTTP 响应是 200。服务端可能返回 400(JSON 格式错)、401(token 过期)、500(服务异常)等。
必须配合 CURLOPT_HEADERFUNCTION 或更简单的 CURLOPT_NOBODY + curl_easy_getinfo 获取状态码:
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 200) {
fprintf(stderr, "HTTP error: %ld\n", http_code);
}
- 若需读取响应体,记得设
CURLOPT_WRITEFUNCTION和CURLOPT_WRITEDATA,否则响应内容会被丢弃 - 调试阶段可临时加
CURLOPT_VERBOSE查看完整请求/响应头,但上线前关掉,避免日志泄露敏感字段
libcurl 默认不校验证书,生产环境必须启用 SSL 验证
默认情况下,libcurl 对 HTTPS 请求跳过证书验证(CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST 默认为 1L?不,实际是 0L —— 早期版本默认关闭,新版本仍建议显式设置)。不校验等于把通信裸奔在中间人攻击下。
正确做法:
- 设
CURLOPT_SSL_VERIFYPEER为 1L(验证证书链) - 设
CURLOPT_SSL_VERIFYHOST为 2L(验证域名匹配) - 若用自签名证书或内网 CA,通过
CURLOPT_CAINFO指定 PEM 格式根证书路径,而非关闭验证 - Windows 上可能还需
CURLOPT_CAINFO或CURLOPT_CAPATH,因为系统证书库 libcurl 不自动读取
最容易被忽略的是:即使你写了 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L),但如果没提供证书路径且系统无默认 CA bundle,curl 会静默失败并返回 CURLE_SSL_CACERT,而不是抛异常。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











