c++怎么调用web api接口_c++ libcurl库引入与HTTP POST请求【实战】

libcurl是C++调用Web API最成熟跨平台选择;Linux用apt安装,macOS用Homebrew,Windows推荐vcpkg;发JSON POST需设CURLOPT_POSTFIELDS、Content-Type头、WriteCallback,并处理重定向、gzip、SSL验证等细节。

用 C++ 调用 Web API 接口,libcurl 是最成熟、跨平台、可控性最强的选择;它不依赖 Qt 或 Boost 等大型框架,适合嵌入式、服务端或轻量 CLI 工具场景。

怎么引入 libcurl(Windows / Linux / macOS)

不同系统下,libcurl 的获取和链接方式差异明显,直接决定后续能否编译通过:

  • Linux(Ubuntu/Debian):sudo apt install libcurl4-openssl-dev,编译时加 -lcurl
  • macOS:用 Homebrew 安装 brew install curl,头文件在 /opt/homebrew/include/curl/(Apple Silicon),链接时加 -lcurl,注意可能需指定路径:-L/opt/homebrew/lib
  • Windows:推荐用 vcpkg:vcpkg install curl:x64-windows,然后在 CMake 中 find_package(CURL REQUIRED);手动链接容易漏 ws2_32.libwldap32.lib,导致 undefined reference to 'curl_easy_init'

怎么发一个标准 JSON POST 请求

多数 Web API 要求 Content-Type: application/json,且请求体是 UTF-8 编码的 JSON 字符串。关键点不在“发出去”,而在“发得对”:

  • 必须调用 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str.c_str()),不能只设 URL 后靠 GET 拼参
  • 必须显式设置 Content-Type header:struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  • json_str 必须是 std::string(非 const char* 临时字面量),否则 curl 可能在发送中途读到已释放内存
  • 务必检查返回值:CURLcode res = curl_easy_perform(curl);res != CURLE_OK 时,用 curl_easy_strerror(res) 查错,而不是只看 HTTP 状态码
#include 
#include 
#include 

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

int main() { CURL* curl; CURLcode res; std::string readBuffer; std::string json = R"({"name":"Alice","age":30})";

curl = curl_easy_init();
if (!curl) return -1;

curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, json.length());

struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);

res = curl_easy_perform(curl);
if (res != CURLE_OK) {
    std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << "\n";
} else {
    long http_code = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
    std::cout << "HTTP " << http_code << "\n" << readBuffer << "\n";
}

curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return 0;

}

为什么 response 返回空或乱码?常见陷阱

不是接口没响应,而是 libcurl 默认不处理重定向、不自动解压、不校验证书——这些都得手动开:

  • 遇到 301/302 重定向但没跳转?补上:curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  • 返回 gzip 压缩内容却显示乱码?加:curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");(空字符串表示接受所有编码,libcurl 自动解压)
  • HTTPS 请求失败,报 SSL certificate problem?开发阶段可临时禁用验证:curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);(上线前必须删掉)
  • 中文字段在 response 里变成 \u4f60\u597d?那是服务器返回了 Unicode 转义,不是 libcurl 的问题;解析 JSON 时用支持 UTF-8 的库(如 nlohmann/json),别用手工 substr

真正难的不是写通第一个请求,而是让错误可定位、超时可控制、证书可配置、JSON 可解析、重定向可追溯——这些细节堆起来,才构成一次生产可用的 API 调用。