diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index e4d5f05e11..67701ae538 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -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; } @@ -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 body, int code) = 0; }; using abstract_conn_ptr = std::shared_ptr; @@ -167,6 +167,21 @@ namespace eosio { } catch(...) {} return 0; } + + /** + * Helper method to calculate the "in flight" size of a std::optional + * When the optional doesn't contain value, it will return the size of 0 + * + * @param o - the std::optional where T is typename + * @return in flight size of o + */ + template + static size_t in_flight_sizeof( const std::optional& o ) { + if( o ) { + return in_flight_sizeof( *o ); + } + return 0; + } } using websocket_server_type = websocketpp::server>; @@ -238,7 +253,7 @@ class http_plugin_impl : public std::enable_shared_from_this { } } - ssl_context_ptr on_tls_init(websocketpp::connection_hdl hdl) { + ssl_context_ptr on_tls_init() { ssl_context_ptr ctx = websocketpp::lib::make_shared(asio::ssl::context::sslv23_server); try { @@ -383,7 +398,7 @@ class http_plugin_impl : public std::enable_shared_from_this { _impl->requests_in_flight += 1; } - ~abstract_conn_impl() { + ~abstract_conn_impl() override { _impl->requests_in_flight -= 1; } @@ -405,8 +420,10 @@ class http_plugin_impl : public std::enable_shared_from_this { http_plugin_impl::handle_exception(_conn); } - void send_response(std::string body, int code) override { - _conn->set_body(std::move(body)); + void send_response(std::optional 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(); } @@ -472,15 +489,15 @@ class http_plugin_impl : public std::enable_shared_from_this { * 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; } @@ -516,7 +533,7 @@ class http_plugin_impl : public std::enable_shared_from_this { 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 resp) { then(code, std::move(resp)); }; @@ -525,7 +542,7 @@ class http_plugin_impl : public std::enable_shared_from_this { 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(); } @@ -541,7 +558,7 @@ class http_plugin_impl : public std::enable_shared_from_this { * @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( ... ) { @@ -558,8 +575,8 @@ class http_plugin_impl : public std::enable_shared_from_this { * @return lambda suitable for url_response_callback */ template - 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 response ) { auto tracked_response = make_in_flight(std::move(response), my); if (!abstract_conn_ptr->verify_max_bytes_in_flight()) { return; @@ -569,9 +586,13 @@ class http_plugin_impl : public std::enable_shared_from_this { 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(); } @@ -649,7 +670,7 @@ class http_plugin_impl : public std::enable_shared_from_this { } } - 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); @@ -664,7 +685,7 @@ class http_plugin_impl : public std::enable_shared_from_this { http_plugin::http_plugin():my(new http_plugin_impl()){ app().register_config_type(); } - 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()) @@ -861,7 +882,7 @@ class http_plugin_impl : public std::enable_shared_from_this { 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( my->unix_server.get_con_from_hdl(hdl)); + my->handle_http_request( my->unix_server.get_con_from_hdl(std::move(hdl))); }); my->unix_server.start_accept(); } catch ( const fc::exception& e ){ @@ -879,8 +900,8 @@ class http_plugin_impl : public std::enable_shared_from_this { 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" ); @@ -900,7 +921,7 @@ class http_plugin_impl : public std::enable_shared_from_this { 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(); diff --git a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp index 15189fed18..b9f1378f0f 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp @@ -14,7 +14,7 @@ namespace eosio { * * Arguments: response_code, response_body */ - using url_response_callback = std::function; + using url_response_callback = std::function)>; /** * @brief Callback type for a URL handler @@ -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(); @@ -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();