in Release/src/http/listener/http_server_asio.cpp [634:759]
will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::system::error_code& ec)
{
auto thisRequest = http_request::_create_request(make_unique<linux_request_context>());
set_request(thisRequest);
if (ec)
{
// client closed connection
if (ec == boost::asio::error::eof || // peer has performed an orderly shutdown
ec ==
boost::asio::error::operation_aborted || // this can be removed. ECONNABORTED happens only for accept()
ec == boost::asio::error::connection_reset || // connection reset by peer
ec == boost::asio::error::timed_out // connection timed out
)
{
return finish_request_response();
}
else
{
thisRequest._reply_if_not_already(status_codes::BadRequest);
m_close = true;
(will_erase_from_parent_t) do_bad_response();
(will_deref_t) deref();
return will_deref_and_erase_t {};
}
}
else
{
// read http status line
std::istream request_stream(&m_request_buf);
request_stream.imbue(std::locale::classic());
std::skipws(request_stream);
web::http::method http_verb;
#ifndef _UTF16_STRINGS
request_stream >> http_verb;
#else
{
std::string tmp;
request_stream >> tmp;
http_verb = utility::conversions::latin1_to_utf16(tmp);
}
#endif
if (boost::iequals(http_verb, methods::GET))
http_verb = methods::GET;
else if (boost::iequals(http_verb, methods::POST))
http_verb = methods::POST;
else if (boost::iequals(http_verb, methods::PUT))
http_verb = methods::PUT;
else if (boost::iequals(http_verb, methods::DEL))
http_verb = methods::DEL;
else if (boost::iequals(http_verb, methods::HEAD))
http_verb = methods::HEAD;
else if (boost::iequals(http_verb, methods::TRCE))
http_verb = methods::TRCE;
else if (boost::iequals(http_verb, methods::CONNECT))
http_verb = methods::CONNECT;
else if (boost::iequals(http_verb, methods::OPTIONS))
http_verb = methods::OPTIONS;
// Check to see if there is not allowed character on the input
if (!web::http::details::validate_method(http_verb))
{
thisRequest.reply(status_codes::BadRequest);
m_close = true;
(will_erase_from_parent_t) do_bad_response();
(will_deref_t) deref();
return will_deref_and_erase_t {};
}
thisRequest.set_method(http_verb);
std::string http_path_and_version;
std::getline(request_stream, http_path_and_version);
const size_t VersionPortionSize = sizeof(" HTTP/1.1\r") - 1;
// Make sure path and version is long enough to contain the HTTP version
if (http_path_and_version.size() < VersionPortionSize + 2)
{
thisRequest.reply(status_codes::BadRequest);
m_close = true;
(will_erase_from_parent_t) do_bad_response();
(will_deref_t) deref();
return will_deref_and_erase_t {};
}
// Get the path - remove the version portion and prefix space
try
{
thisRequest.set_request_uri(utility::conversions::to_string_t(
http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1)));
}
catch (const std::exception& e) // may be std::range_error indicating invalid Unicode, or web::uri_exception
{
thisRequest.reply(status_codes::BadRequest, e.what());
m_close = true;
(will_erase_from_parent_t) do_bad_response();
(will_deref_t) deref();
return will_deref_and_erase_t {};
}
// Get the version
std::string http_version =
http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2);
auto requestImpl = thisRequest._get_impl().get();
web::http::http_version parsed_version = web::http::http_version::from_string(http_version);
requestImpl->_set_http_version(parsed_version);
// if HTTP version is 1.0 then disable pipelining
if (parsed_version == web::http::http_versions::HTTP_1_0)
{
m_close = true;
}
// Get the remote IP address
boost::system::error_code socket_ec;
auto endpoint = m_socket->remote_endpoint(socket_ec);
if (!socket_ec)
{
requestImpl->_set_remote_address(utility::conversions::to_string_t(endpoint.address().to_string()));
}
return handle_headers();
}
}