Skip to content

Commit

Permalink
Merge pull request #1000 from AntelopeIO/GH-678-http-debug-3.2
Browse files Browse the repository at this point in the history
[3.2] Log all http request/response at debug log level
  • Loading branch information
heifner authored Apr 11, 2023
2 parents c716ac5 + d4bd548 commit 480374b
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
10 changes: 9 additions & 1 deletion plugins/http_plugin/http_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,22 +489,30 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
my->plugin_state->url_handlers[url] = my->make_http_thread_url_handler(handler);
}

void http_plugin::handle_exception( const char *api_name, const char *call_name, const string& body, const url_response_callback& cb) {
void http_plugin::handle_exception( const char* api_name, const char* call_name, const string& body, const url_response_callback& cb) {
try {
try {
throw;
} catch (chain::unknown_block_exception& e) {
error_results results{400, "Unknown Block", error_results::error_info(e, verbose_http_errors)};
cb( 400, fc::time_point::maximum(), fc::variant( results ));
fc_dlog( logger(), "Unknown block while processing ${api}.${call}: ${e}",
("api", api_name)("call", call_name)("e", e.to_detail_string()) );
} catch (chain::invalid_http_request& e) {
error_results results{400, "Invalid Request", error_results::error_info(e, verbose_http_errors)};
cb( 400, fc::time_point::maximum(), fc::variant( results ));
fc_dlog( logger(), "Invalid http request while processing ${api}.${call}: ${e}",
("api", api_name)("call", call_name)("e", e.to_detail_string()) );
} catch (chain::unsatisfied_authorization& e) {
error_results results{401, "UnAuthorized", error_results::error_info(e, verbose_http_errors)};
cb( 401, fc::time_point::maximum(), fc::variant( results ));
fc_dlog( logger(), "Auth error while processing ${api}.${call}: ${e}",
("api", api_name)("call", call_name)("e", e.to_detail_string()) );
} catch (chain::tx_duplicate& e) {
error_results results{409, "Conflict", error_results::error_info(e, verbose_http_errors)};
cb( 409, fc::time_point::maximum(), fc::variant( results ));
fc_dlog( logger(), "Duplicate trx while processing ${api}.${call}: ${e}",
("api", api_name)("call", call_name)("e", e.to_detail_string()) );
} catch (fc::eof_exception& e) {
error_results results{422, "Unprocessable Entity", error_results::error_info(e, verbose_http_errors)};
cb( 422, fc::time_point::maximum(), fc::variant( results ));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ class beast_http_listener : public std::enable_shared_from_this<beast_http_liste
fail(ec, "accept", self->plugin_state_->logger, "closing connection");
} else {
// Create the session object and run it
std::string remote_endpoint = boost::lexical_cast<std::string>(self->socket_.remote_endpoint());
std::make_shared<session_type>(
std::move(self->socket_),
self->plugin_state_)
self->plugin_state_,
std::move(remote_endpoint))
->run_session();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include <eosio/http_plugin/common.hpp>
#include <fc/io/json.hpp>

#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

#include <memory>
#include <string>

Expand Down Expand Up @@ -75,6 +78,26 @@ bool allow_host(const http::request<http::string_body>& req, T& session,
return true;
}

// T can be request or response or anything serializable to boost iostreams
template<typename T>
std::string to_log_string(const T& req, size_t max_size = 1024) {
assert( max_size > 4 );
std::string buffer( max_size, '\0' );
{
boost::iostreams::array_sink sink( buffer.data(), buffer.size() );
boost::iostreams::stream stream( sink );
stream << req;
}
buffer.resize( std::strlen( buffer.data() ) );
if( buffer.size() == max_size ) {
buffer[max_size - 3] = '.';
buffer[max_size - 2] = '.';
buffer[max_size - 1] = '.';
}
std::replace_if( buffer.begin(), buffer.end(), []( unsigned char c ) { return c == '\r' || c == '\n'; }, ' ' );
return buffer;
}

// Handle HTTP conneciton using boost::beast for TCP communication
// Subclasses of this class (plain_session, ssl_session, etc.)
// use the Curiously Recurring Template Pattern so that
Expand All @@ -95,6 +118,7 @@ class beast_http_session : public detail::abstract_conn {
std::optional<http::response<http::string_body>> res_;

std::shared_ptr<http_plugin_state> plugin_state_;
std::string remote_endpoint_;

// whether response should be sent back to client when an exception occurs
bool is_send_exception_response_ = true;
Expand Down Expand Up @@ -147,6 +171,9 @@ class beast_http_session : public detail::abstract_conn {
// verfiy bytes in flight/requests in flight
if(!verify_max_bytes_in_flight()) return;

fc_dlog( plugin_state_->logger, "Request: ${ep} ${r}",
("ep", remote_endpoint_)("r", to_log_string(req)) );

std::string resource = std::string(req.target());
// look for the URL handler to handle this resource
auto handler_itr = plugin_state_->url_handlers.find(resource);
Expand Down Expand Up @@ -215,9 +242,9 @@ class beast_http_session : public detail::abstract_conn {
// shared_from_this() requires default constructor
beast_http_session() = default;

beast_http_session(
std::shared_ptr<http_plugin_state> plugin_state)
: plugin_state_(std::move(plugin_state)) {
beast_http_session(std::shared_ptr<http_plugin_state> plugin_state, std::string remote_endpoint)
: plugin_state_(std::move(plugin_state)),
remote_endpoint_(std::move(remote_endpoint)) {
plugin_state_->requests_in_flight += 1;
req_parser_.emplace();
req_parser_->body_limit(plugin_state_->max_body_size);
Expand Down Expand Up @@ -372,6 +399,9 @@ class beast_http_session : public detail::abstract_conn {
// Determine if we should close the connection after
bool close = !(plugin_state_->keep_alive) || res_->need_eof();

fc_dlog( plugin_state_->logger, "Response: ${ep} ${b}",
("ep", remote_endpoint_)("b", to_log_string(*res_)) );

// Write the response
auto self = derived().shared_from_this();
http::async_write(
Expand Down Expand Up @@ -400,8 +430,9 @@ class plain_session
// Create the session
plain_session(
tcp_socket_t socket,
std::shared_ptr<http_plugin_state> plugin_state)
: beast_http_session<plain_session>(std::move(plugin_state)), socket_(std::move(socket)) {}
std::shared_ptr<http_plugin_state> plugin_state,
std::string remote_endpoint)
: beast_http_session<plain_session>(std::move(plugin_state), std::move(remote_endpoint)), socket_(std::move(socket)) {}

tcp_socket_t& stream() { return socket_; }
tcp_socket_t& socket() { return socket_; }
Expand Down Expand Up @@ -445,8 +476,10 @@ class ssl_session

ssl_session(
tcp_socket_t socket,
std::shared_ptr<http_plugin_state> plugin_state)
: beast_http_session<ssl_session>(std::move(plugin_state)), stream_(std::move(socket), *plugin_state_->ctx) {}
std::shared_ptr<http_plugin_state> plugin_state,
std::string remote_endpoint)
: beast_http_session<ssl_session>(std::move(plugin_state), std::move(remote_endpoint)),
stream_(std::move(socket), *plugin_state_->ctx) {}


ssl::stream<tcp_socket_t>& stream() { return stream_; }
Expand Down Expand Up @@ -512,8 +545,9 @@ class unix_socket_session

public:
unix_socket_session(stream_protocol::socket sock,
std::shared_ptr<http_plugin_state> plugin_state)
: beast_http_session(std::move(plugin_state)), socket_(std::move(sock)) {}
std::shared_ptr<http_plugin_state> plugin_state,
std::string remote_endpoint)
: beast_http_session(std::move(plugin_state), std::move(remote_endpoint)), socket_(std::move(sock)) {}

virtual ~unix_socket_session() = default;

Expand Down

0 comments on commit 480374b

Please sign in to comment.