libcurl 把代理配置附加到执行传输的 easy handle 上。在该 handle 上设置中间服务器的地址,同时让 CURLOPT_URL 保持为目标 URL。

下面的代码片段假定 libcurl 已初始化,且 handle 是有效的 easy handle:

char error[CURL_ERROR_SIZE] = {0};
CURLcode result;

result = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, error);
if (result == CURLE_OK)
    result = curl_easy_setopt(handle, CURLOPT_URL,
                              "https://example.com/");
if (result == CURLE_OK)
    result = curl_easy_setopt(handle, CURLOPT_PROXY,
                              "http://proxy.example:8080");
if (result == CURLE_OK)
    result = curl_easy_perform(handle);

if (result != CURLE_OK)
    fprintf(stderr, "%s\n", error[0] ? error
                                  : curl_easy_strerror(result));

只要 handle 还引用错误缓冲区,就要让它保持有效。在离开其作用域之前,请清理该 handle,或者替换或清除它的 CURLOPT_ERRORBUFFER 指针。代理主机名只是占位符;HTTP 代理列表中未经认证的候选项可以为这个公开站点测试提供地址。请使用它实际的 scheme 和端口,并检查它是否允许 HTTPS 隧道。

HTTPS 目标也可以使用 HTTP 代理。libcurl 会为该 HTTPS 传输处理隧道。代理选项中的 http:// 描述的是到中间服务器的连接。只有当代理端点确实接受 TLS,且 libcurl 构建支持时,才把它改成 https://。

让实际生效的路由成为有意为之

显式代理选项会覆盖对应的代理环境设置。绕过是另一个独立决定:继承来的 no_proxy 仍可能排除目标。如果这个 handle 必须对它收到的每个目标都使用选定的代理,请把 CURLOPT_NOPROXY 配置为空字符串,作为该策略的一部分。

反过来,把 CURLOPT_PROXY 设为空字符串会显式禁用代理。把它设为 NULL 则会移除显式赋值,并重新允许基于环境的行为。这两个值服务于不同的目的。

像 Content-Type: text/xml 这样的目标专用标头并不会选择代理。只有当实际请求正文和目标 API 需要该媒体类型时,才添加它。

也要读取 HTTP 结果

curl_easy_perform 成功并不意味着网站返回了成功的 HTTP 状态。请读取 CURLINFO_RESPONSE_CODE 并应用应用程序的状态处理。代理的 CONNECT 回复有自己的值 CURLINFO_HTTP_CONNECTCODE;隧道拒绝会先于任何网站响应出现。

CURLOPT_FAILONERROR 可以把许多 HTTP 错误视为失败,但它的文档特别指出了身份验证例外。请把代理的 407 质询与目标的状态分开处理。

相关文章