Отправить тело сообщения после заголовка ответа процесса с помощью libcurl

TL; DR: Как сказано в теме — нужно отправлять многочастное сообщение ТОЛЬКО после заголовков ответа процесса, полученных после установленного соединения.

Согласно документации libcurl, CURLOPT_HEADERFUNCTION вызывается libcurl, как только он получает данные заголовка.
Но после простого расследования этого не произошло.

Как воспроизвести:

Callbacks:

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 [Дата: Пн, 15 Фев 2016 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: Flags [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: Flags [S.], seq 1336121630, ack 164841210, win 14480, варианты [mss 1460, sackOK, TS val 2083933652 ecr 2164947, nop, wscale 7 ], длина 0

13: 36: 30.639337 IP 192.168.1.70.41895> 74.112.184.85.https: Flags [.], 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: Flags [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: Flags [.], Ack 297, win 122, options [nop, nop, TS val 2083933866 ecr 2165000], длина 0

13: 36: 30.861507 IP 74.112.184.85.https> 192.168.1.70.41895: Flags [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: Flags [.], 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: Flags [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: Flags [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: Flags [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: Flags [.], 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: Flags [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: Flags [.], Seq 870: 2218, ack 2741, win 271, варианты [nop, nop, TS val 2165360 ecr 2083934344], длина 1348

повторение отправки данных

Из-за SSL-соединения я не могу просмотреть tcpdump с -A, чтобы быть уверенным, что заголовки получены в предложенной части.

Программного обеспечения:

  • Libcurl (7,36)
  • Компилятор GCC (4.8.4)

Постскриптум Мне кажется, что libcurl неправильно работает для [RFC 2616 (8.2.4)] (https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html)

P.P.S То же поведение, если существует. Соединение: закрыть заголовок.

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]