in Release/src/http/client/http_client_asio.cpp [1419:1514]
void read_headers()
{
auto needChunked = false;
std::istream response_stream(&m_body_buf);
response_stream.imbue(std::locale::classic());
std::string header;
while (std::getline(response_stream, header) && header != "\r")
{
const auto colon = header.find(':');
if (colon != std::string::npos)
{
auto name = header.substr(0, colon);
auto value = header.substr(colon + 1, header.size() - colon - 2);
boost::algorithm::trim(name);
boost::algorithm::trim(value);
if (boost::iequals(name, header_names::transfer_encoding))
{
needChunked = boost::icontains(value, U("chunked"));
}
if (boost::iequals(name, header_names::connection))
{
// If the server uses HTTP/1.1, then 'Keep-Alive' is the default,
// so connection is explicitly closed only if we get "Connection: close".
// If the server uses HTTP/1.0, it would need to respond using
// 'Connection: Keep-Alive' every time.
if (m_response._get_impl()->http_version() != web::http::http_versions::HTTP_1_0)
m_connection->set_keep_alive(!boost::iequals(value, U("close")));
else
m_connection->set_keep_alive(boost::iequals(value, U("Keep-Alive")));
}
m_response.headers().add(utility::conversions::to_string_t(std::move(name)),
utility::conversions::to_string_t(std::move(value)));
}
}
m_content_length = (std::numeric_limits<size_t>::max)(); // Without Content-Length header, size should be same
// as TCP stream - set it size_t max.
m_response.headers().match(header_names::content_length, m_content_length);
if (!this->handle_compression())
{
// false indicates report_exception was called
return;
}
complete_headers();
// Check for HEAD requests and status codes which cannot contain a
// message body in HTTP/1.1 (see 3.3.3/1 of the RFC 7230).
//
// note: need to check for 'chunked' here as well, azure storage sends both
// transfer-encoding:chunked and content-length:0 (although HTTP says not to)
const auto status = m_response.status_code();
if (m_request.method() == U("HEAD") || (status >= 100 && status < 200) || status == status_codes::NoContent ||
status == status_codes::NotModified || (!needChunked && m_content_length == 0))
{
// we can stop early - no body
const auto& progress = m_request._get_impl()->_progress_handler();
if (progress)
{
try
{
(*progress)(message_direction::download, 0);
}
catch (...)
{
report_exception(std::current_exception());
return;
}
}
complete_request(0);
}
else
{
if (!needChunked)
{
async_read_until_buffersize(
static_cast<size_t>((std::min)(m_content_length,
static_cast<uint64_t>(m_http_client->client_config().chunksize()))),
boost::bind(
&asio_context::handle_read_content, shared_from_this(), boost::asio::placeholders::error));
}
else
{
m_connection->async_read_until(m_body_buf,
CRLF,
boost::bind(&asio_context::handle_chunk_header,
shared_from_this(),
boost::asio::placeholders::error));
}
}
}