Here is what I do: In the header function (set with CURLOPT_HEADERFUNCTION) I read the headers until I get a blank header since a blank header indicates the end of the headers. There is an exception to this however since you can get an HTTP continue header followed by a blank header which is then followed by more headers. Once I get a blank header that is NOT directly following the continue I set a flag to indicatd I’m done reading headers. I also set that flag if the write function (set with CURLOPT_WRITEFUNCTION) gets called as this also indicates that the headers are complete. Once that flag is set, I call curl_easy_getinfo to the response code.
No guarantees that this works with every server but it works with the servers that my app uses. Here is the relevant code: bool IsContinueHeader(const CString& header) { return header.GetLength() > 12 && header.Left(5) == "HTTP/" && header.Right(12) == "100 Continue"; } size_t headerCallback(char* data, size_t size, size_t nmemb, CurlOperationState* state) { CString header = UTF8Convert::UTF8ToWide(std::string_view(data, size * nmemb)); header.TrimRight(); // remove the trailing crlf if (header.IsEmpty()) { // An empty header signals end of headers, but not if it is after a "HTTP/1.1 100 Continue" which comes before reading input data if (!state->m_response_headers.empty()) { const CString& last_header = state->m_response_headers.at(state->m_response_headers.size() - 1); if (!IsContinueHeader(last_header)) state->m_finished_reading_headers = true; } } else { state->m_response_headers.push_back(header); } return size * nmemb; } bool CurlHttpConnection::RunLoop() { int numfds; CURLMcode mc = curl_multi_wait(m_multi_handle, NULL, 0, 1000, &numfds); if (mc != CURLM_OK) throw SyncException(L"Network error"); if (!numfds) Sleep(100); int still_running = 0; curl_multi_perform(m_multi_handle, &still_running); CheckForErrors(); return still_running > 0; } HttpResponse CurlHttpConnection::Request(const HttpRequest& request) { Cleanup(); m_state = std::make_unique<CurlOperationState>(request, m_listener); SetupEasyHandle(); curl_multi_add_handle(m_multi_handle, m_state->m_easy_handle); int still_running; curl_multi_perform(m_multi_handle, &still_running); while (!m_state->m_finished_reading_headers) { RunLoop(); } int http_status; curl_easy_getinfo(m_state->m_easy_handle, CURLINFO_RESPONSE_CODE, &http_status); HttpResponse response(http_status, m_state->m_response_headers); > On Feb 6, 2021, at 1:22 AM, Idan Freiberg via curl-library > <curl-library@cool.haxx.se> wrote: > > Hi curl developers, > > I'm using the multi-stack interface in order to read a large response body in > chunk, with the help of the CURLOPT_WRITEFUNCTION and some code similar to > the one in fcurl project. > > I wonder if its possible to fetch info like response code, cookies, response > headers before the running easy handle is done (which means all the response > body was read). > > Technically reading the response headers should be possible as they are the > first thing received. The thing is i'm not sure how to check they are fully > received after a curl_multi_perform() call? > Some times when using HTTP auth, you will receive the subsequent 401 response > code instead of the actual response code returns after authentication. > > Any suggestions? > > Thanks > > -- > Idan Freiberg > Mobile: +972-52-2925213 > ------------------------------------------------------------------- > Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library > Etiquette: https://curl.se/mail/etiquette.html
------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.html