TL; DR:正如主题所说 - 仅在处理响应标头之后才需要发送多部分帖子正文,在建立连接后收到。
根据 libcurl 文档,CURLOPT_HEADERFUNCTION 在收到标头数据后立即被 libcurl 调用。 但是经过简单的调查,这并没有发生。
如何重现:
回调:
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-继续]
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 未授权]
来自标头的附加信息
正如您所见,libcurl 为自己的需要处理了 100-continue 标头,但仅在发送数据后才调用处理标头的回调。
此外,似乎收到了所有必要的标头。tcpdump 示例:
13:36:30.425361 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [S], seq 164841209, win 29200, options [mss 1460,sackOK,TS val 2164947 ecr 0,nop,wscale 7], 长度 0
13:36:30.639293 IP 74.112.184.85.https > 192.168.1.70.41895:标志 [S.],seq 1336121630,ack 164841210,win 14480,选项 [mss 1460,sackOK,TS val 208393346752 秒,27393346752 秒],长度为 0
13:36:30.639337 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [.], ack 1, win 229, options [nop,nop,TS val 2165000 ecr 2083933652], 长度 0
13:36:30.640031 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [P.], seq 1:297, ack 1, win 229, options [nop,nop,TS val 2165000 ecr 2083933652], 长度 296
13:36:30.853750 IP 74.112.184.85.https > 192.168.1.70.41895:标志 [.],ack 297,win 122,选项 [nop,nop,TS val 2083933866 ecr 2165000],长度 0
13:36:30.861507 IP 74.112.184.85.https > 192.168.1.70.41895:标志 [P.],seq 1:2690,ack 297,win 122,选项 [nop,nop,TS val 2083933874 ecr 2165000],长度 2689
^^^^^ - 就在这里。
13:36:30.861524 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [.], ack 2690, win 271, 选项 [nop,nop,TS val 2165056 ecr 2083933874], 长度 0
13:36:30.862654 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [P.], seq 297:423, ack 2690, win 271, options [nop,nop,TS val 2165056 ecr 2083933874], 长度 126
13:36:31.076949 IP 74.112.184.85.https > 192.168.1.70.41895:标志 [P.],seq 2690:2741,ack 423,win 122,选项 [nop,nop,TS val 2083934090 ecr 2165056],长度 51
13:36:31.077286 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [P.], seq 423:693, ack 2741, win 271, options [nop,nop,TS val 2165110 ecr 2083934090], 长度 270
13:36:31.330808 IP 74.112.184.85.https > 192.168.1.70.41895: 标志 [.], ack 693, win 130, 选项 [nop,nop,TS val 2083934344 ecr 2165110], 长度 0
13:36:32.078397 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [P.], seq 693:870, ack 2741, win 271, options [nop,nop,TS val 2165360 ecr 2083934344], 长度 17
13:36:32.078533 IP 192.168.1.70.41895 > 74.112.184.85.https: 标志 [.], seq 870:2218, ack 2741, win 271, options [nop,nop,TS val 2165360 ecr 2083934344], 长度 1348
重复发送数据
由于 SSL 连接,我无法使用 -A 查看 tcpdump,以确保在建议的部分中收到标头。
软件:
- libcurl(7.36)
- 编译器 GCC(4.8.4)
PS对我来说,似乎libcurl对[RFC 2616(8.2.4)]有错误的行为( https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html )
PPS 如果存在则相同的行为连接:关闭标头。