如何使用CURLOPT_HEADERFUNCTION读取单个响应标头字段? [英] How can I use CURLOPT_HEADERFUNCTION to read a single response header field?

查看:977
本文介绍了如何使用CURLOPT_HEADERFUNCTION读取单个响应标头字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm implementing a C program which needs to read a remote file's size from the Content-Length header (when Content-Length is sent in the response headers).

我查看了libcurl的文档,到目前为止,我能想到的最好的就是CURLOPT_HEADERFUNCTION设置的回调函数.我整理了一个回调的玩具实现,应该将标头打印到STDOUT:

I've looked over libcurl's docs, and the best I've been able to come up with so far has been a callback function for the CURLOPT_HEADERFUNCTION setting. I've put together a toy implementation of a callback, which is supposed to print the headers to STDOUT:

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

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

While I want to be able to print the Content-Length header (or, at least, print all the headers), I can only get this function to print the response code:

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

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

If I comment out the line in my main which sets the callback to the hdf function defined above, the default behaviour is to print all the headers to STDOUT.

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

For reference, here is the main function I'm using, based on a thread on the libcurl mailing list:

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选项编写一个回调,该回调可以将特定的标头加载到内存中或以其他方式进行操作-或至少将所有标头加载到内存中?

How can I write a callback for the CURLOPT_HEADERFUNCTION option which can load a specific header into memory or otherwise manipulate it -- or, at least, load all headers into memory?

推荐答案

我只能使用此函数来打印响应代码:

I can only get this function to print the response code:

对此的答案在 CURLOPT_HEADERFUNCTION 文档中:

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

This function gets called by libcurl as soon as it has received header data. The header callback will be called once for each header and only complete header lines are passed on to the callback. Parsing headers is very easy using this. The size of the data pointed to by buffer is size multiplied with nmemb. Do not assume that the header line is zero terminated! The pointer named userdata is the one you set with the CURLOPT_HEADERDATA option. This callback function must return the number of bytes actually taken care of. If that amount differs from the amount passed in to your function, it'll signal an error to the library. This will cause the transfer to get aborted and the libcurl function in progress will return CURLE_WRITE_ERROR.

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

Your printf() call is assuming null termination, and your callback is returning fewer bytes than provided, so you are aborting the response after the first response line is received.

试试看.

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选项编写一个回调,该回调可以将特定的标头加载到内存中或以其他方式进行操作-或至少将所有标头加载到内存中?

How can I write a callback for the CURLOPT_HEADERFUNCTION option which can load a specific header into memory or otherwise manipulate it -- or, at least, load all headers into memory?

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

Once you fix your bug, you should be able to see all headers. You can then parse b looking for the Content-Length header, and when found save its data to a buffer that you pass to userdata via CURLOPT_HEADERDATA.

现在,有了这样的说法,有一种更简单的方法来检索Content-Length值.使用curl_easy_perform()(CURLOPT_NOBODY)执行HEAD请求,如果成功,则使用curl_easy_getinfo()检索 CURLINFO_CONTENT_LENGTH_DOWNLOAD 值:

Now, with that said, there is an easier way to retrieve the Content-Length value. Perform a HEAD request with curl_easy_perform() (CURLOPT_NOBODY), and if successful than use curl_easy_getinfo() to retrieve the CURLINFO_CONTENT_LENGTH_DOWNLOAD value:

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

CURLINFO_CONTENT_LENGTH_DOWNLOAD
Content length from the Content-Length header.

这篇关于如何使用CURLOPT_HEADERFUNCTION读取单个响应标头字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆