使用libcurl

时间:2016-02-15 11:55:40

标签: c++ libcurl box rfc rfc2616

TL; DR:正如主题所说 - 只需要在建立连接后收到的进程响应头之后发送多部分帖子正文。

根据libcurl文档,CURLOPT_HEADERFUNCTION gets called by libcurl as soon as it has received header data. 但经过简单的调查后,这种情况并没有发生。

如何重现:

回调:

size_t HeaderCallback(void *data, size_t size, size_t nmemb, void *userdata) {
    cout << __FUNCTION__ << " " << data << '\n';
    return size*nmemb;
}

static int Trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp) {
    cout << __FUNCTION__  << " " <<timestamp<< ' ' << data << endl;
    return 0;
}

static size_t ReadFromStateCallBack(void* dst, size_t size, size_t nmemb, void* state) {    
    cout << __FUNCTION__  << " " <<timestamp<< endl;
    return READ();
}

主要请求主体:

CURL *curl = curl_easy_init();
curl_slist* h = NULL;
const char * url = "https://upload.box.com/api/2.0/files/content";

curl_httppost *formpost=NULL;
curl_httppost *lastptr=NULL;

curl_formadd(&formpost,&lastptr,
             CURLFORM_COPYNAME, "filename",
             CURLFORM_CONTENTTYPE, "text/plain",
             CURLFORM_FILENAME, "uploadthis.txt",
             CURLFORM_STREAM, (void*)state,
             CURLFORM_CONTENTSLENGTH, GetFileSize(),
             CURLFORM_END);

curl_formadd(&formpost, &lastptr,
    CURLFORM_COPYNAME, "parent_id",
    CURLFORM_COPYCONTENTS, "0",
    CURLFORM_END);

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, Trace);

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);

curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderCallback);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadFromStateCallBack);
curl_easy_setopt(curl, CURLOPT_READDATA, state);

curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buf);

h = curl_slist_append(h, "Expect: 100-continue");
h = curl_slist_append(h, "Authorization: Bearer WRONGTOKEN");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, h);

curl_easy_perform(curl);

curl_formfree(formpost);

然后我们可以重温下一个日志(自c ++ 11 chrono epoch以来的大量时间):

  

输入[0]数据:[SSL相关内容]

     

键入[0]数据:[完成等待100-continue]

     

ReadFromStateCallBack 1455532592078426519

     

...

     

ReadFromStateCallBack 1455532592507779449

     

HeaderCallback 1455532592937695923 [HTTP / 1.1 100继续]

     

HeaderCallback 1455532592937713786 [日期:星期一,2016年2月15日10:36:32 GMT]

     

键入[0]数据:[服务器ATS未列入黑名单]

     

HeaderCallback:1455532593030759917 [HTTP / 1.1 401 Unauthorized]

     

来自标题的其他信息

正如你可以看到自己需要的libcurl处理了100-continue标头,但是只有在发送数据后才调用处理标头的回调。

似乎还收到了所有必需的标题。 tcpdump示例:

  

13:36:30.425361 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [S],seq 164841209,win 29200,options [mss 1460,sackOK,TS val 2164947 ecr 0,nop,wscale 7],length 0

     

13:36:30.639293 IP 74.112.184.85.https&gt; 192.168.1.70.41895:Flags [S.],seq 1336121630,ack 164841210,win 14480,options [mss 1460,sackOK,TS val 2083933652 ecr 2164947,nop,wscale 7],length 0

     

13:36:30.639337 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [。],ack 1,win 229,options [nop,nop,TS val 2165000 ecr 2083933652],length 0

     

13:36:30.640031 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [P.],seq 1:297,ack 1,win 229,options [nop,nop,TS val 2165000 ecr 2083933652],length 296

     

13:36:30.853750 IP 74.112.184.85.https&gt; 192.168.1.70.41895:Flags [。],ack 297,win 122,options [nop,nop,TS val 2083933866 ecr 2165000],length 0

     

13:36:30.861507 IP 74.112.184.85.https&gt; 192.168.1.70.41895:Flags [P.],seq 1:2690,ack 297,win 122,options [nop,nop,TS val 2083933874 ecr 2165000],length 2689

^^^^^ - 就在这里。

  

13:36:30.861524 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [。],ack 2690,win 271,options [nop,nop,TS val 2165056 ecr 2083933874],length 0

     

13:36:30.862654 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [P.],seq 297:423,ack 2690,win 271,options [nop,nop,TS val 2165056 ecr 2083933874],length 126

     

13:36:31.076949 IP 74.112.184.85.https&gt; 192.168.1.70.41895:Flags [P.],seq 2690:2741,ack 423,win 122,options [nop,nop,TS val 2083934090 ecr 2165056],length 51

     

13:36:31.077286 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [P.],seq 423:693,ack 2741,win 271,options [nop,nop,TS val 2165110 ecr 2083934090],length 270

     

13:36:31.330808 IP 74.112.184.85.https&gt; 192.168.1.70.41895:Flags [。],ack 693,win 130,options [nop,nop,TS val 2083934344 ecr 2165110],length 0

     

13:36:32.078397 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [P.],seq 693:870,ack 2741,win 271,options [nop,nop,TS val 2165360 ecr 2083934344],长度177

     

13:36:32.078533 IP 192.168.1.70.41895&gt; 74.112.184.85.https:Flags [。],seq 870:2218,ack 2741,win 271,options [nop,nop,TS val 2165360 ecr 2083934344],length 1348

     

重复发送数据

由于SSL连接,我无法使用-A查看tcpdump,以确保在建议的部分中收到标头。

软件:

  • 的libcurl(7.36)
  • 编译器GCC(4.8.4)

P.S。对我来说,似乎libcurl对[RFC 2616(8.2.4)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

有错误的行为

P.P.S相同的行为如果存在连接:关闭标题。

0 个答案:

没有答案