void windows_request_context::read_headers_io_completion()

in Release/src/http/listener/http_server_httpsys.cpp [476:610]


void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD)
{
    if (error_code != NO_ERROR)
    {
        m_msg.reply(status_codes::InternalError);
        init_response_callbacks(ShouldWaitForBody::DontWait);
    }
    else
    {
        utility::string_t header;
        std::string badRequestMsg;
        try
        {
            // HTTP_REQUEST::pRawUrl contains the raw URI that came across the wire.
            // Use this instead since the CookedUrl is a mess of the URI components
            // some encoded and some not.
            m_msg.set_request_uri(utf8_to_utf16(m_request->pRawUrl));
        }
        catch (const uri_exception& e)
        {
            // If an exception occurred, finish processing the request below but
            // respond with BadRequest instead of dispatching to the user's
            // request handlers.
            badRequestMsg = e.what();
        }
        m_msg.set_method(parse_request_method(m_request));
        parse_http_headers(m_request->Headers, m_msg.headers());

        // See if we need to compress or decompress the incoming request body, and if so, prepare for it
        try
        {
            if (m_msg.headers().match(header_names::transfer_encoding, header))
            {
                try
                {
                    m_decompressor = http::compression::details::get_decompressor_from_header(
                        header, http::compression::details::header_types::transfer_encoding);
                }
                catch (http_exception& e)
                {
                    if (e.error_code().value() != status_codes::NotImplemented)
                    {
                        // Something is wrong with the header; we'll fail here
                        throw;
                    }
                    // We could not find a decompressor; we'll see if the user's handler adds one later
                    m_decompress_header_type = http::compression::details::header_types::transfer_encoding;
                    m_decompress_header = std::move(header);
                }
            }
            else if (m_msg.headers().match(header_names::content_encoding, header))
            {
                try
                {
                    m_decompressor = http::compression::details::get_decompressor_from_header(
                        header, http::compression::details::header_types::content_encoding);
                }
                catch (http_exception& e)
                {
                    if (e.error_code().value() != status_codes::UnsupportedMediaType)
                    {
                        // Something is wrong with the header; we'll fail here
                        throw;
                    }
                    // We could not find a decompressor; we'll see if the user's handler adds one later
                    m_decompress_header_type = http::compression::details::header_types::content_encoding;
                    m_decompress_header = std::move(header);
                }
            }
            else if (m_msg.headers().match(header_names::te, header))
            {
                // Note that init_response_headers throws away m_msg, so we need to set our compressor here.  If
                // the header contains all unsupported algorithms, it's not an error -- we just won't compress
                m_compressor = http::compression::details::get_compressor_from_header(
                    header, http::compression::details::header_types::te);
            }
            else if (m_msg.headers().match(header_names::accept_encoding, header))
            {
                // This would require pre-compression of the input stream, since we MUST send Content-Length, so we'll
                // (legally) ignore it
                // m_compressor = http::compression::details::get_compressor_from_header(header,
                // http::compression::details::header_types:accept_encoding);
            }
        }
        catch (http_exception& e)
        {
            if (badRequestMsg.empty())
            {
                // Respond with a reasonable message
                badRequestMsg = e.what();
            }
        }

        m_msg._get_impl()->_set_http_version(
            {(uint8_t)m_request->Version.MajorVersion, (uint8_t)m_request->Version.MinorVersion});

        // Retrieve the remote IP address
        std::vector<wchar_t> remoteAddressBuffer(50);

        if (m_request->Address.pRemoteAddress->sa_family == AF_INET6)
        {
            auto inAddr = &reinterpret_cast<SOCKADDR_IN6*>(m_request->Address.pRemoteAddress)->sin6_addr;
            InetNtopW(AF_INET6, inAddr, &remoteAddressBuffer[0], remoteAddressBuffer.size());
        }
        else if (m_request->Address.pRemoteAddress->sa_family == AF_INET)
        {
            auto inAddr = &reinterpret_cast<SOCKADDR_IN*>(m_request->Address.pRemoteAddress)->sin_addr;
            InetNtopW(AF_INET, inAddr, &remoteAddressBuffer[0], remoteAddressBuffer.size());
        }
        else
        {
            remoteAddressBuffer[0] = L'\0';
        }

        m_msg._get_impl()->_set_remote_address(&remoteAddressBuffer[0]);

        // Start reading in body from the network.
        m_msg._get_impl()->_prepare_to_receive_data();
        read_request_body_chunk();

        // Dispatch request to the http_listener.
        if (badRequestMsg.empty())
        {
            dispatch_request_to_listener(
                (web::http::experimental::listener::details::http_listener_impl*)m_request->UrlContext);
        }
        else
        {
            m_msg.reply(status_codes::BadRequest, badRequestMsg);

            // Even though we have a bad request, we should wait for the body otherwise we risk racing over m_overlapped
            init_response_callbacks(ShouldWaitForBody::Wait);
        }
    }
}