1

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 クロノエポックからの多数の時間):

タイプ [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 Unauthorized]

ヘッダーからの追加情報

また、ご覧のとおり、libcurl は 100-continue ヘッダーを処理する必要がありますが、ヘッダーを処理するためのコールバックはデータの送信後にのみ呼び出されます。

また、必要なすべてのヘッダーが受信されたようです。tcpdump の例:

13:36:30.425361 IP 192.168.1.70.41895 > 74.112.184.85.https: フラグ [S]、seq 164841209、win 29200、オプション [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 2083933652 ]、長さ 0

13:36:30.639337 IP 192.168.1.70.41895 > 74.112.184.85.https: フラグ [.]、ack 1、win 229、オプション [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、オプション [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、オプション [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、オプション [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、勝利 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、オプション [nop、nop、TS val 2165360 ecr 2083934344]、長さ 177

13:36:32.078533 IP 192.168.1.70.41895 > 74.112.184.85.https: フラグ [.]、seq 870:2218、ack 2741、win 271、オプション [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 存在する場合は同じ動作 接続: ヘッダーを閉じます。

4

0 に答える 0