Merge branch 'feature/new-rpc-ws-clients' into feature/son-for-ethereum
This commit is contained in:
commit
73163d2722
2 changed files with 85 additions and 38 deletions
|
|
@ -1,10 +1,15 @@
|
||||||
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
|
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/asio/buffers_iterator.hpp>
|
||||||
|
#include <boost/beast/core.hpp>
|
||||||
|
#include <boost/beast/http.hpp>
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/xpressive/xpressive.hpp>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
|
@ -18,6 +23,35 @@ rpc_client::rpc_client(std::string _url, std::string _user, std::string _passwor
|
||||||
password(_password),
|
password(_password),
|
||||||
debug_rpc_calls(_debug_rpc_calls),
|
debug_rpc_calls(_debug_rpc_calls),
|
||||||
request_id(0) {
|
request_id(0) {
|
||||||
|
|
||||||
|
std::string reg_expr = "^((?P<Protocol>https|http):\\/\\/)?(?P<Host>[a-zA-Z0-9\\-\\.]+)(:(?P<Port>\\d{1,5}))?(?P<Target>\\/.+)?";
|
||||||
|
boost::xpressive::sregex sr = boost::xpressive::sregex::compile(reg_expr);
|
||||||
|
|
||||||
|
boost::xpressive::smatch sm;
|
||||||
|
|
||||||
|
if (boost::xpressive::regex_search(url, sm, sr)) {
|
||||||
|
protocol = sm["Protocol"];
|
||||||
|
if (protocol.empty()) {
|
||||||
|
protocol = "http";
|
||||||
|
}
|
||||||
|
|
||||||
|
host = sm["Host"];
|
||||||
|
if (host.empty()) {
|
||||||
|
host + "localhost";
|
||||||
|
}
|
||||||
|
|
||||||
|
port = sm["Port"];
|
||||||
|
if (port.empty()) {
|
||||||
|
port = "80";
|
||||||
|
}
|
||||||
|
|
||||||
|
target = sm["Target"];
|
||||||
|
if (target.empty()) {
|
||||||
|
target = "/";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
elog("Invalid URL: ${url}", ("url", url));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) {
|
std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) {
|
||||||
|
|
@ -98,57 +132,65 @@ std::string rpc_client::send_post_request(std::string method, std::string params
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t write_callback(char *ptr, size_t size, size_t nmemb, rpc_reply *reply) {
|
|
||||||
size_t retval = 0;
|
|
||||||
if (reply != nullptr) {
|
|
||||||
reply->body.append(ptr, size * nmemb);
|
|
||||||
retval = size * nmemb;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc_reply rpc_client::send_post_request(std::string body, bool show_log) {
|
rpc_reply rpc_client::send_post_request(std::string body, bool show_log) {
|
||||||
|
|
||||||
struct curl_slist *headers = nullptr;
|
// The io_context is required for all I/O
|
||||||
headers = curl_slist_append(headers, "Accept: application/json");
|
boost::beast::net::io_context ioc;
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
|
||||||
headers = curl_slist_append(headers, "charset: utf-8");
|
|
||||||
|
|
||||||
CURL *curl = curl_easy_init();
|
// These objects perform our I/O
|
||||||
|
boost::beast::net::ip::tcp::resolver resolver(ioc);
|
||||||
|
boost::beast::tcp_stream stream(ioc);
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
// Look up the domain name
|
||||||
if (url.find("https://", 0) == 0) {
|
auto const results = resolver.resolve(host, port);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.empty()) {
|
// Make the connection on the IP address we get from a lookup
|
||||||
curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str());
|
stream.connect(results);
|
||||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
// Set up an HTTP GET request message
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
boost::beast::http::request<boost::beast::http::string_body> req{boost::beast::http::verb::post, target, 11};
|
||||||
|
req.set(boost::beast::http::field::host, host + ":" + port);
|
||||||
|
req.set(boost::beast::http::field::accept, "application/json");
|
||||||
|
req.set(boost::beast::http::field::content_type, "application/json");
|
||||||
|
req.set(boost::beast::http::field::content_encoding, "utf-8");
|
||||||
|
req.set(boost::beast::http::field::content_length, body.length());
|
||||||
|
req.body() = body;
|
||||||
|
|
||||||
//curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
|
// Send the HTTP request to the remote host
|
||||||
|
boost::beast::http::write(stream, req);
|
||||||
|
|
||||||
|
// This buffer is used for reading and must be persisted
|
||||||
|
boost::beast::flat_buffer buffer;
|
||||||
|
|
||||||
|
// Declare a container to hold the response
|
||||||
|
boost::beast::http::response<boost::beast::http::dynamic_body> res;
|
||||||
|
|
||||||
|
// Receive the HTTP response
|
||||||
|
boost::beast::http::read(stream, buffer, res);
|
||||||
|
|
||||||
|
//// Write the message to standard out
|
||||||
|
//std::cout << res << std::endl;
|
||||||
|
|
||||||
|
// Gracefully close the socket
|
||||||
|
boost::beast::error_code ec;
|
||||||
|
stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
|
||||||
|
|
||||||
|
// not_connected happens sometimes
|
||||||
|
// so don't bother reporting it.
|
||||||
|
//
|
||||||
|
if (ec && ec != boost::beast::errc::not_connected)
|
||||||
|
throw boost::beast::system_error{ec};
|
||||||
|
|
||||||
|
std::string rbody{boost::asio::buffers_begin(res.body().data()),
|
||||||
|
boost::asio::buffers_end(res.body().data())};
|
||||||
rpc_reply reply;
|
rpc_reply reply;
|
||||||
|
reply.status = 200;
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
reply.body = rbody;
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply);
|
|
||||||
|
|
||||||
curl_easy_perform(curl);
|
|
||||||
|
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &reply.status);
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
curl_slist_free_all(headers);
|
|
||||||
|
|
||||||
if (show_log) {
|
if (show_log) {
|
||||||
ilog("### Request URL: ${url}", ("url", url));
|
ilog("### Request URL: ${url}", ("url", url));
|
||||||
ilog("### Request: ${body}", ("body", body));
|
ilog("### Request: ${body}", ("body", body));
|
||||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
ilog("### Response: ${rbody}", ("rbody", rbody));
|
||||||
ilog("### Response: ${ss}", ("ss", ss.str()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,11 @@ protected:
|
||||||
std::string send_post_request(std::string method, std::string params, bool show_log);
|
std::string send_post_request(std::string method, std::string params, bool show_log);
|
||||||
|
|
||||||
std::string url;
|
std::string url;
|
||||||
|
std::string protocol;
|
||||||
|
std::string host;
|
||||||
|
std::string port;
|
||||||
|
std::string target;
|
||||||
|
|
||||||
std::string user;
|
std::string user;
|
||||||
std::string password;
|
std::string password;
|
||||||
bool debug_rpc_calls;
|
bool debug_rpc_calls;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue