用libcurl发graphql查询需构造合法json post请求,设content-type为application/json,用json库生成请求体,正确配置curlopt_url、postfields、httpheader和ssl_verifypeer,并手动解析响应中的"errors"字段判断执行失败。

用 libcurl 发送 GraphQL 查询最直接
GraphQL 本质是 HTTP POST 请求,请求体是 JSON,响应也是 JSON。C++ 没有原生 GraphQL 客户端,但用 libcurl 构造标准 POST 就能跑通——这是绝大多数生产项目的实际做法。
关键不是“怎么用 GraphQL”,而是“怎么发对的 JSON POST”。常见错误是把查询当 GET 参数拼在 URL 后,或漏掉 Content-Type: application/json,导致服务端返回 400 或 405。
- 必须设
Content-Type为application/json,否则 GraphQL 服务(如 Apollo、Hasura)会拒绝解析 - 查询字符串要 JSON 编码,不能裸写
{ query: "{ user { id }" }——引号、转义、嵌套都要合法 - 推荐用
jsoncpp或nlohmann/json生成请求体,避免手拼字符串出错
// 示例:用 nlohmann/json 构造请求体
#include <nlohmann/json.hpp>
nlohmann::json req;
req["query"] = R"(query GetUser($id: ID!) { user(id: $id) { name email } })";
req["variables"] = {{"id", "123"}};
std::string body = req.dump(); // 自动处理引号和转义
curl_easy_setopt 必设的四个选项
只调 curl_easy_perform 肯定失败。漏掉任一关键选项,轻则返回空响应,重则连接超时或 400 错误。
-
CURLOPT_URL:必须是完整 endpoint,比如https://api.example.com/graphql,不能少/graphql -
CURLOPT_POSTFIELDS:传body.c_str(),不是body.data();且别设CURLOPT_POST为 1L——CURLOPT_POSTFIELDS已隐含 POST -
CURLOPT_HTTPHEADER:至少加"Content-Type: application/json",有些服务还要求"Authorization: Bearer xxx" -
CURLOPT_SSL_VERIFYPEER:调试时可设为 0L 绕过证书校验,但上线前必须恢复为 1L,否则 HTTPS 请求失败
变量传入失败?检查 variables 字段结构
很多人写对了 query 字段,却卡在变量不生效——问题几乎全出在 variables 的 JSON 结构上。
立即学习“C++免费学习笔记(深入)”;
GraphQL 规范要求 variables 是一个对象(map),键名必须和查询中 $xxx 的名字完全一致,值类型也要匹配 schema。常见错误包括:
- 把
variables写成数组([{"id": "123"}])而不是对象({"id": "123"}) - 整数变量传成字符串(
"age": "25"而非"age": 25),触发类型校验失败 - 空对象
{}被忽略,但某些服务要求显式传"variables": {}(尤其带默认变量时)
如果返回 "Variable '$x' has invalid value",优先打印原始 body 字符串,用 jq 或在线 JSON 校验器看结构是否合法。
错误响应没报错?别忽略 CURLOPT_FAILONERROR
默认情况下,libcurl 对 4xx/5xx 响应码仍会返回 CURLE_OK,只是把响应体(比如 {"errors": [...]})照常吐给你。结果就是程序以为成功了,其实 GraphQL 执行失败了。
- 务必设置
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L),让 4xx/5xx 直接触发curl_easy_perform返回错误 - 但注意:开启后,HTTP 302 重定向也会被当成错误——如果服务端用了重定向,得额外配
CURLOPT_FOLLOWLOCATION - 更稳妥的做法是:关掉
CURLOPT_FAILONERROR,手动检查响应状态码 + 解析响应体里的errors数组
真正容易被忽略的是:GraphQL 错误不等于 HTTP 错误。一个 200 响应里可能包含 {"data": null, "errors": [...]},这种必须靠解析 JSON 判断,不能只看 HTTP 状态码。










