【问题标题】:How can I use CURLOPT_HEADERFUNCTION to read a single response header field?如何使用 CURLOPT_HEADERFUNCTION 读取单个响应标头字段?
【发布时间】:2016-09-27 18:12:30
【问题描述】:

我正在实现一个 C 程序,它需要从 Content-Length 标头中读取远程文件的大小(当在响应标头中发送 Content-Length 时)。

我查看了 libcurl 的文档,到目前为止我能想到的最好的方法是 CURLOPT_HEADERFUNCTION 设置的回调函数。我已经整理了一个回调的玩具实现,它应该将标题打印到STDOUT

size_t hdf(char* b, size_t size, size_t nitems, void *userdata) {
    printf("%s", b);
    return 0;
}

虽然我希望能够打印 Content-Length 标头(或者至少打印所有标头),但我只能使用此函数来打印响应代码:

$ ./curltest "some_url_which_sends_back_Content_Length"
HTTP/1.1 200 OK

如果我在main 中注释掉将回调设置为上面定义的hdf 函数的行,则默认行为是将所有标题打印到STDOUT

作为参考,这是我正在使用的 main 函数,基于 libcurl 邮件列表中的一个线程:

int main(int argc, char *argv[]) 
{ 
   CURLcode ret; 
   CURL *hnd = curl_easy_init(); 
   curl_easy_setopt(hnd, CURLOPT_URL, argv[1]); 
   curl_easy_setopt(hnd, CURLOPT_HEADER, 1); 
   curl_easy_setopt(hnd, CURLOPT_NOBODY, 1);
   curl_easy_setopt(hnd, CURLOPT_HEADERFUNCTION, hdf);
   ret = curl_easy_perform(hnd);
   curl_easy_cleanup(hnd);
}

如何为 CURLOPT_HEADERFUNCTION 选项编写回调,它可以将特定标头加载到内存中或以其他方式对其进行操作——或者至少将所有标头加载到内存中?

【问题讨论】:

    标签: c libcurl


    【解决方案1】:

    我只能得到这个函数来打印响应码:

    答案在CURLOPT_HEADERFUNCTION 文档中:

    libcurl 在收到标头数据后立即调用此函数。标头回调将为每个标头调用一次,并且仅将完整的标头行传递给回调。使用它解析标题非常容易。 buffer指向的数据大小是大小乘以nmemb。不要假设标题行以零结尾!名为 userdata 的指针是您使用 CURLOPT_HEADERDATA 选项设置的指针。 此回调函数必须返回实际处理的字节数。如果该数量与传递给您的函数的数量不同,它将向库发出错误信号。这将导致传输中止,并且正在进行的 libcurl 函数将返回 CURLE_WRITE_ERROR

    您的printf() 调用假定为空终止,并且您的回调返回的字节数少于提供的字节数,因此您在收到第一条响应行后中止响应。

    试试这个。

    size_t hdf(char* b, size_t size, size_t nitems, void *userdata) {
        size_t numbytes = size * nitems;
        printf("%.*s\n", numbytes, b);
        return numbytes;
    }
    

    如何为 CURLOPT_HEADERFUNCTION 选项编写一个回调,该选项可以将特定标头加载到内存中或以其他方式对其进行操作——或者至少将所有标头加载到内存中?

    修复错误后,您应该能够看到所有标题。然后,您可以解析 b 以查找 Content-Length 标头,并在找到时将其数据保存到您通过 CURLOPT_HEADERDATA 传递给 userdata 的缓冲区中。

    现在,话虽如此,有一种更简单的方法可以检索 Content-Length 值。使用curl_easy_perform() (CURLOPT_NOBODY) 执行HEAD 请求,如果成功则使用curl_easy_getinfo() 检索CURLINFO_CONTENT_LENGTH_DOWNLOAD 值:

    CURLINFO_CONTENT_LENGTH_DOWNLOAD
    来自 Content-Length 标头的内容长度。

    【讨论】:

    • D'oh,我必须更加注意文档。谢谢你的解释!
    猜你喜欢
    • 2014-05-24
    • 2011-08-25
    • 2017-01-13
    • 2017-09-06
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2016-09-02
    相关资源
    最近更新 更多