Fix regression introduced by 100-continue (#1949)
* Fix regression introduced by 100-continue * Remove superfluous capture
This commit is contained in:
parent
30a8a8d7f3
commit
ba09b64c81
2 changed files with 78 additions and 89 deletions
|
@ -54,104 +54,91 @@ void nano::rpc_connection::write_result (std::string body, unsigned version, boo
|
|||
void nano::rpc_connection::read ()
|
||||
{
|
||||
auto this_l (shared_from_this ());
|
||||
boost::system::error_code header_error;
|
||||
auto header_parser (std::make_shared<boost::beast::http::request_parser<boost::beast::http::empty_body>> ());
|
||||
std::promise<size_t> header_available_promise;
|
||||
std::future<size_t> header_available = header_available_promise.get_future ();
|
||||
header_parser->body_limit (rpc_config.max_request_size);
|
||||
if (!network_constants.is_test_network ())
|
||||
{
|
||||
boost::beast::http::async_read_header (socket, buffer, *header_parser, [this_l, header_parser, &header_available_promise, &header_error](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
size_t header_response_bytes_written = 0;
|
||||
if (!ec)
|
||||
boost::beast::http::async_read_header (socket, buffer, *header_parser, [this_l, header_parser](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
if (!ec)
|
||||
{
|
||||
if (boost::iequals (header_parser->get ()[boost::beast::http::field::expect], "100-continue"))
|
||||
{
|
||||
if (boost::iequals (header_parser->get ()[boost::beast::http::field::expect], "100-continue"))
|
||||
auto continue_response (std::make_shared<boost::beast::http::response<boost::beast::http::empty_body>> ());
|
||||
continue_response->version (11);
|
||||
continue_response->result (boost::beast::http::status::continue_);
|
||||
continue_response->set (boost::beast::http::field::server, "nano");
|
||||
boost::beast::http::async_write (this_l->socket, *continue_response, [this_l, continue_response](boost::system::error_code const & ec, size_t bytes_transferred) {});
|
||||
}
|
||||
|
||||
this_l->parse_request (header_parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
this_l->logger.always_log ("RPC header error: ", ec.message ());
|
||||
|
||||
// Respond with the reason for the invalid header
|
||||
auto response_handler ([this_l](std::string const & tree_a) {
|
||||
this_l->write_result (tree_a, 11);
|
||||
boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
this_l->write_completion_handler (this_l);
|
||||
});
|
||||
});
|
||||
json_error_response (response_handler, std::string ("Invalid header: ") + ec.message ());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void nano::rpc_connection::parse_request (std::shared_ptr<boost::beast::http::request_parser<boost::beast::http::empty_body>> header_parser)
|
||||
{
|
||||
auto this_l (shared_from_this ());
|
||||
auto body_parser (std::make_shared<boost::beast::http::request_parser<boost::beast::http::string_body>> (std::move (*header_parser)));
|
||||
boost::beast::http::async_read (socket, buffer, *body_parser, [this_l, body_parser](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
if (!ec)
|
||||
{
|
||||
// equivalent to background
|
||||
this_l->io_ctx.post ([this_l, body_parser]() {
|
||||
auto & req (body_parser->get ());
|
||||
auto start (std::chrono::steady_clock::now ());
|
||||
auto version (req.version ());
|
||||
std::string request_id (boost::str (boost::format ("%1%") % boost::io::group (std::hex, std::showbase, reinterpret_cast<uintptr_t> (this_l.get ()))));
|
||||
auto response_handler ([this_l, version, start, request_id](std::string const & tree_a) {
|
||||
auto body = tree_a;
|
||||
this_l->write_result (body, version);
|
||||
boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
this_l->write_completion_handler (this_l);
|
||||
});
|
||||
|
||||
this_l->logger.always_log (boost::str (boost::format ("RPC request %2% completed in: %1% microseconds") % std::chrono::duration_cast<std::chrono::microseconds> (std::chrono::steady_clock::now () - start).count () % request_id));
|
||||
});
|
||||
auto method = req.method ();
|
||||
switch (method)
|
||||
{
|
||||
boost::beast::http::response<boost::beast::http::empty_body> continue_response;
|
||||
continue_response.version (11);
|
||||
continue_response.result (boost::beast::http::status::continue_);
|
||||
continue_response.set (boost::beast::http::field::server, "nano");
|
||||
auto response_size (boost::beast::http::async_write (this_l->socket, continue_response, boost::asio::use_future));
|
||||
header_response_bytes_written = response_size.get ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header_error = ec;
|
||||
this_l->logger.always_log ("RPC header error: ", ec.message ());
|
||||
}
|
||||
|
||||
header_available_promise.set_value (header_response_bytes_written);
|
||||
});
|
||||
|
||||
// Await header
|
||||
header_available.get ();
|
||||
}
|
||||
|
||||
if (!header_error)
|
||||
{
|
||||
auto body_parser (std::make_shared<boost::beast::http::request_parser<boost::beast::http::string_body>> (std::move (*header_parser)));
|
||||
boost::beast::http::async_read (socket, buffer, *body_parser, [this_l, body_parser](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
if (!ec)
|
||||
{
|
||||
// equivalent to background
|
||||
this_l->io_ctx.post ([this_l, body_parser]() {
|
||||
auto & req (body_parser->get ());
|
||||
auto start (std::chrono::steady_clock::now ());
|
||||
auto version (req.version ());
|
||||
std::string request_id (boost::str (boost::format ("%1%") % boost::io::group (std::hex, std::showbase, reinterpret_cast<uintptr_t> (this_l.get ()))));
|
||||
auto response_handler ([this_l, version, start, request_id](std::string const & tree_a) {
|
||||
auto body = tree_a;
|
||||
this_l->write_result (body, version);
|
||||
case boost::beast::http::verb::post:
|
||||
{
|
||||
auto handler (std::make_shared<nano::rpc_handler> (this_l->rpc_config, req.body (), request_id, response_handler, this_l->rpc_handler_interface, this_l->logger));
|
||||
handler->process_request ();
|
||||
break;
|
||||
}
|
||||
case boost::beast::http::verb::options:
|
||||
{
|
||||
this_l->prepare_head (version);
|
||||
this_l->res.prepare_payload ();
|
||||
boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
this_l->write_completion_handler (this_l);
|
||||
});
|
||||
|
||||
this_l->logger.always_log (boost::str (boost::format ("RPC request %2% completed in: %1% microseconds") % std::chrono::duration_cast<std::chrono::microseconds> (std::chrono::steady_clock::now () - start).count () % request_id));
|
||||
});
|
||||
auto method = req.method ();
|
||||
switch (method)
|
||||
{
|
||||
case boost::beast::http::verb::post:
|
||||
{
|
||||
auto handler (std::make_shared<nano::rpc_handler> (this_l->rpc_config, req.body (), request_id, response_handler, this_l->rpc_handler_interface, this_l->logger));
|
||||
handler->process_request ();
|
||||
break;
|
||||
}
|
||||
case boost::beast::http::verb::options:
|
||||
{
|
||||
this_l->prepare_head (version);
|
||||
this_l->res.prepare_payload ();
|
||||
boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
this_l->write_completion_handler (this_l);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
json_error_response (response_handler, "Can only POST requests");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this_l->logger.always_log ("RPC read error: ", ec.message ());
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Respond with the reason for the invalid header
|
||||
auto response_handler ([this_l](std::string const & tree_a) {
|
||||
this_l->write_result (tree_a, 11);
|
||||
boost::beast::http::async_write (this_l->socket, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) {
|
||||
this_l->write_completion_handler (this_l);
|
||||
default:
|
||||
{
|
||||
json_error_response (response_handler, "Can only POST requests");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
json_error_response (response_handler, std::string ("Invalid header: ") + header_error.message ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this_l->logger.always_log ("RPC read error: ", ec.message ());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void nano::rpc_connection::write_completion_handler (std::shared_ptr<nano::rpc_connection> rpc_connection)
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
virtual void write_completion_handler (std::shared_ptr<nano::rpc_connection> rpc_connection);
|
||||
void prepare_head (unsigned version, boost::beast::http::status status = boost::beast::http::status::ok);
|
||||
void write_result (std::string body, unsigned version, boost::beast::http::status status = boost::beast::http::status::ok);
|
||||
void parse_request (std::shared_ptr<boost::beast::http::request_parser<boost::beast::http::empty_body>> header_parser);
|
||||
|
||||
void read ();
|
||||
|
||||
boost::asio::ip::tcp::socket socket;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue