void read_headers()

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));
            }
        }
    }