Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.2] Allow HTTP-RPC with empty response #630

Merged
merged 1 commit into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 45 additions & 24 deletions plugins/http_plugin/http_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace eosio {

static http_plugin_defaults current_http_plugin_defaults;

void http_plugin::set_defaults(const http_plugin_defaults config) {
void http_plugin::set_defaults(const http_plugin_defaults& config) {
current_http_plugin_defaults = config;
}

Expand Down Expand Up @@ -128,11 +128,11 @@ namespace eosio {
* virtualized wrapper for the various underlying connection functions needed in req/resp processng
*/
struct abstract_conn {
virtual ~abstract_conn() {}
virtual ~abstract_conn() = default;
virtual bool verify_max_bytes_in_flight() = 0;
virtual bool verify_max_requests_in_flight() = 0;
virtual void handle_exception() = 0;
virtual void send_response(std::string, int) = 0;
virtual void send_response(std::optional<std::string> body, int code) = 0;
};

using abstract_conn_ptr = std::shared_ptr<abstract_conn>;
Expand Down Expand Up @@ -167,6 +167,21 @@ namespace eosio {
} catch(...) {}
return 0;
}

/**
* Helper method to calculate the "in flight" size of a std::optional<T>
* When the optional doesn't contain value, it will return the size of 0
*
* @param o - the std::optional<T> where T is typename
* @return in flight size of o
*/
template<typename T>
static size_t in_flight_sizeof( const std::optional<T>& o ) {
if( o ) {
return in_flight_sizeof( *o );
}
return 0;
}
}

using websocket_server_type = websocketpp::server<detail::asio_with_stub_log<websocketpp::transport::asio::basic_socket::endpoint>>;
Expand Down Expand Up @@ -238,7 +253,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
}
}

ssl_context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
ssl_context_ptr on_tls_init() {
ssl_context_ptr ctx = websocketpp::lib::make_shared<websocketpp::lib::asio::ssl::context>(asio::ssl::context::sslv23_server);

try {
Expand Down Expand Up @@ -383,7 +398,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
_impl->requests_in_flight += 1;
}

~abstract_conn_impl() {
~abstract_conn_impl() override {
_impl->requests_in_flight -= 1;
}

Expand All @@ -405,8 +420,10 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
http_plugin_impl::handle_exception<T>(_conn);
}

void send_response(std::string body, int code) override {
_conn->set_body(std::move(body));
void send_response(std::optional<std::string> body, int code) override {
if( body ) {
_conn->set_body( std::move( *body ) );
}
_conn->set_status( websocketpp::http::status_code::value( code ) );
_conn->send_http_response();
}
Expand Down Expand Up @@ -472,15 +489,15 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
* const accessor
* @return const reference to the contained object
*/
const T& operator* () const {
const T& obj() const {
return _object;
}

/**
* mutable accessor (can be moved frmo)
* mutable accessor (can be moved from)
* @return mutable reference to the contained object
*/
T& operator* () {
T& obj() {
return _object;
}

Expand Down Expand Up @@ -516,7 +533,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
return;
}

url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, fc::variant resp) {
url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, std::optional<fc::variant> resp) {
then(code, std::move(resp));
};

Expand All @@ -525,7 +542,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
app().post( priority, [next_ptr, conn=std::move(conn), r=std::move(r), tracked_b, wrapped_then=std::move(wrapped_then)]() mutable {
try {
// call the `next` url_handler and wrap the response handler
(*next_ptr)( std::move( r ), std::move(*(*tracked_b)), std::move(wrapped_then)) ;
(*next_ptr)( std::move( r ), std::move(tracked_b->obj()), std::move(wrapped_then)) ;
} catch( ... ) {
conn->handle_exception();
}
Expand All @@ -541,7 +558,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
* @return the constructed internal_url_handler
*/
static detail::internal_url_handler make_http_thread_url_handler(url_handler next) {
return [next=std::move(next)]( detail::abstract_conn_ptr conn, string r, string b, url_response_callback then ) {
return [next=std::move(next)]( const detail::abstract_conn_ptr& conn, string r, string b, url_response_callback then ) {
try {
next(std::move(r), std::move(b), std::move(then));
} catch( ... ) {
Expand All @@ -558,8 +575,8 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
* @return lambda suitable for url_response_callback
*/
template<typename T>
auto make_http_response_handler( detail::abstract_conn_ptr abstract_conn_ptr) {
return [my=shared_from_this(), abstract_conn_ptr]( int code, fc::variant response ) {
auto make_http_response_handler( const detail::abstract_conn_ptr& abstract_conn_ptr) {
return [my=shared_from_this(), abstract_conn_ptr]( int code, std::optional<fc::variant> response ) {
auto tracked_response = make_in_flight(std::move(response), my);
if (!abstract_conn_ptr->verify_max_bytes_in_flight()) {
return;
Expand All @@ -569,9 +586,13 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
boost::asio::post( my->thread_pool->get_executor(),
[my, abstract_conn_ptr, code, tracked_response=std::move(tracked_response)]() {
try {
std::string json = fc::json::to_string( *(*tracked_response), fc::time_point::now() + my->max_response_time );
auto tracked_json = make_in_flight(std::move(json), my);
abstract_conn_ptr->send_response(std::move(*(*tracked_json)), code);
if( tracked_response->obj().has_value() ) {
std::string json = fc::json::to_string( *tracked_response->obj(), fc::time_point::now() + my->max_response_time );
auto tracked_json = make_in_flight( std::move( json ), my );
abstract_conn_ptr->send_response( std::move( tracked_json->obj() ), code );
} else {
abstract_conn_ptr->send_response( {}, code );
}
} catch( ... ) {
abstract_conn_ptr->handle_exception();
}
Expand Down Expand Up @@ -649,7 +670,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
}
}

void add_aliases_for_endpoint( const tcp::endpoint& ep, string host, string port ) {
void add_aliases_for_endpoint( const tcp::endpoint& ep, const string& host, const string& port ) {
auto resolved_port_str = std::to_string(ep.port());
valid_hosts.emplace(host + ":" + port);
valid_hosts.emplace(host + ":" + resolved_port_str);
Expand All @@ -664,7 +685,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
http_plugin::http_plugin():my(new http_plugin_impl()){
app().register_config_type<https_ecdh_curve_t>();
}
http_plugin::~http_plugin(){}
http_plugin::~http_plugin() = default;

void http_plugin::set_program_options(options_description&, options_description& cfg) {
if(current_http_plugin_defaults.default_unix_socket_path.length())
Expand Down Expand Up @@ -861,7 +882,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
my->unix_server.listen(*my->unix_endpoint);
// captures `this`, my needs to live as long as unix_server is handling requests
my->unix_server.set_http_handler([this](connection_hdl hdl) {
my->handle_http_request<detail::asio_local_with_stub_log>( my->unix_server.get_con_from_hdl(hdl));
my->handle_http_request<detail::asio_local_with_stub_log>( my->unix_server.get_con_from_hdl(std::move(hdl)));
});
my->unix_server.start_accept();
} catch ( const fc::exception& e ){
Expand All @@ -879,8 +900,8 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {
if(my->https_listen_endpoint) {
try {
my->create_server_for_endpoint(*my->https_listen_endpoint, my->https_server);
my->https_server.set_tls_init_handler([this](websocketpp::connection_hdl hdl) -> ssl_context_ptr{
return my->on_tls_init(hdl);
my->https_server.set_tls_init_handler([this](const websocketpp::connection_hdl& hdl) -> ssl_context_ptr{
return my->on_tls_init();
});

fc_ilog( logger, "start listening for https requests" );
Expand All @@ -900,7 +921,7 @@ class http_plugin_impl : public std::enable_shared_from_this<http_plugin_impl> {

add_api({{
std::string("/v1/node/get_supported_apis"),
[&](string, string body, url_response_callback cb) mutable {
[&](const string&, string body, url_response_callback cb) mutable {
try {
if (body.empty()) body = "{}";
auto result = (*this).get_supported_apis();
Expand Down
10 changes: 5 additions & 5 deletions plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace eosio {
*
* Arguments: response_code, response_body
*/
using url_response_callback = std::function<void(int,fc::variant)>;
using url_response_callback = std::function<void(int,std::optional<fc::variant>)>;

/**
* @brief Callback type for a URL handler
Expand Down Expand Up @@ -65,13 +65,13 @@ namespace eosio {
{
public:
http_plugin();
virtual ~http_plugin();
~http_plugin() override;

//must be called before initialize
static void set_defaults(const http_plugin_defaults config);
static void set_defaults(const http_plugin_defaults& config);

APPBASE_PLUGIN_REQUIRES()
virtual void set_program_options(options_description&, options_description& cfg) override;
void set_program_options(options_description&, options_description& cfg) override;

void plugin_initialize(const variables_map& options);
void plugin_startup();
Expand Down Expand Up @@ -134,7 +134,7 @@ namespace eosio {

static const uint8_t details_limit = 10;

error_info() {};
error_info() = default;

error_info(const fc::exception& exc, bool include_full_log) {
code = exc.code();
Expand Down