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