You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libcurl进行Digest认证时收到两个响应,如何仅获取第二个?

解决libcurl Digest认证时回调多次响应的问题

针对你遇到的Digest认证导致回调收到两次响应(401+200)的问题,可以通过以下方式让libcurl仅保留最终200响应的状态码、响应头和内容:

核心思路

利用libcurl的CURLOPT_HEADERFUNCTION单独处理响应头,在回调中识别状态码,仅标记并保留成功响应(200系列)的头和体数据;同时配合CURLOPT_WRITEFUNCTION过滤无效响应的body内容。

具体实现步骤

1. 定义响应数据结构体

用来存储响应状态、状态码、头和体内容:

#include <string>
#include <cstdio>
#include <curl/curl.h>

struct ResponseData {
    bool is_valid_response;  // 标记当前是否为有效响应
    long status_code;        // 响应状态码
    std::string header;      // 响应头内容
    std::string body;        // 响应体内容
};

2. 实现响应头回调函数

在回调中解析状态行,判断响应是否有效,仅保存有效响应的头信息:

size_t header_callback(char* buffer, size_t size, size_t nitems, void* userdata) {
    ResponseData* resp = static_cast<ResponseData*>(userdata);
    const size_t total_size = size * nitems;

    // 匹配HTTP状态行(格式如:HTTP/1.1 200 OK)
    if (strncmp(buffer, "HTTP/", 5) == 0) {
        // 提取状态码
        sscanf(buffer, "HTTP/%*d.%*d %ld", &resp->status_code);
        // 仅将200-299区间的状态码视为有效响应
        resp->is_valid_response = (resp->status_code >= 200 && resp->status_code < 300);
        
        // 若为无效响应,清空之前积累的内容
        if (!resp->is_valid_response) {
            resp->header.clear();
            resp->body.clear();
        }
    }

    // 仅当响应有效时,保存头内容
    if (resp->is_valid_response) {
        resp->header.append(buffer, total_size);
    }

    return total_size;
}

3. 实现响应体回调函数

仅处理有效响应的body数据:

size_t write_callback(char* buffer, size_t size, size_t nitems, void* userdata) {
    ResponseData* resp = static_cast<ResponseData*>(userdata);
    const size_t total_size = size * nitems;

    // 仅处理有效响应的body
    if (resp->is_valid_response) {
        resp->body.append(buffer, total_size);
    }

    // 无论是否处理,都返回接收的总大小,避免libcurl报错
    return total_size;
}

4. 配置并执行curl请求

设置认证方式、回调函数,执行请求后即可获取仅包含200响应的数据:

int main() {
    curl_global_init(CURL_GLOBAL_ALL);
    CURL* curl = curl_easy_init();

    if (curl) {
        ResponseData resp{};  // 初始化结构体

        // 设置请求URL
        curl_easy_setopt(curl, CURLOPT_URL, "http://你的IP摄像头地址");
        // 启用Digest认证
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
        // 设置用户名密码
        curl_easy_setopt(curl, CURLOPT_USERPWD, "用户名:密码");

        // 绑定头回调函数及数据
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &resp);
        // 绑定体回调函数及数据
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);

        // 执行请求
        const CURLcode res = curl_easy_perform(curl);
        if (res == CURLE_OK) {
            // 输出有效响应的内容
            printf("状态码: %ld\n", resp.status_code);
            printf("响应头:\n%s\n", resp.header.c_str());
            printf("响应体:\n%s\n", resp.body.c_str());
        } else {
            fprintf(stderr, "请求失败: %s\n", curl_easy_strerror(res));
        }

        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

关键说明

  • 无需设置CURLOPT_HEADER,该选项会将头和体混合传入WRITEFUNCTION,而使用CURLOPT_HEADERFUNCTION可以更精准地处理头信息。
  • libcurl 7.72完全支持上述所有选项,无需版本兼容问题。
  • 该方案会自动忽略Digest认证过程中产生的401响应,仅保留最终成功的200响应数据。

内容的提问来源于stack exchange,提问作者bogdan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:12:05