1#include <xrpl/basics/Log.h>
2#include <xrpl/beast/core/LexicalCast.h>
3#include <xrpl/net/AutoSocket.h>
4#include <xrpl/net/HTTPClient.h>
5#include <xrpl/net/HTTPClientSSLContext.h>
7#include <boost/asio.hpp>
8#include <boost/asio/ip/resolver_query_base.hpp>
9#include <boost/asio/ip/tcp.hpp>
10#include <boost/asio/ssl.hpp>
11#include <boost/regex.hpp>
45 boost::asio::io_context& io_context,
46 unsigned short const port,
67 osRequest <<
"GET " << strPath
73 "Connection: close\r\n\r\n";
85 boost::system::error_code
const& ecResult,
106 boost::system::error_code
const& ecResult,
120 std::placeholders::_1,
121 std::placeholders::_2),
136 boost::asio::ip::resolver_query_base::numeric_service);
143 catch (boost::system::system_error
const& e)
164 std::placeholders::_1,
165 std::placeholders::_2));
175 if (ecResult == boost::asio::error::operation_aborted)
178 JLOG(
j_.
trace()) <<
"Deadline cancelled.";
184 JLOG(
j_.
trace()) <<
"Deadline error: " <<
mDeqSites[0] <<
": " << ecResult.message();
191 JLOG(
j_.
trace()) <<
"Deadline arrived.";
196 boost::system::errc::bad_address, boost::system::system_category()};
213 JLOG(
j_.
trace()) <<
"Shutdown error: " <<
mDeqSites[0] <<
": " << ecResult.message();
219 boost::system::error_code
const& ecResult,
220 boost::asio::ip::tcp::resolver::results_type result)
237 JLOG(
j_.
trace()) <<
"Resolve complete.";
239 boost::asio::async_connect(
260 JLOG(
j_.
trace()) <<
"Connected.";
278 AutoSocket::ssl_socket::client,
302 JLOG(
j_.
trace()) <<
"Session started.";
311 std::placeholders::_1,
312 std::placeholders::_2));
338 std::placeholders::_1,
339 std::placeholders::_2));
348 JLOG(
j_.
trace()) <<
"Header: \"" << strHeader <<
"\"";
350 static boost::regex
const reStatus{
"\\`HTTP/1\\S+ (\\d{3}) .*\\'"};
351 static boost::regex
const reSize{
352 "\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'", boost::regex::icase};
353 static boost::regex
const reBody{
"\\`.*\\r\\n\\r\\n(.*)\\'"};
355 boost::smatch smMatch;
357 if (!boost::regex_match(strHeader, smMatch, reStatus))
360 JLOG(
j_.
trace()) <<
"No status code";
362 boost::system::error_code{
363 boost::system::errc::bad_address, boost::system::system_category()});
369 if (boost::regex_match(strHeader, smMatch, reBody))
373 if (boost::regex_match(strHeader, smMatch, reSize))
380 JLOG(
j_.
trace()) <<
"Response field too large";
382 boost::system::error_code{
383 boost::system::errc::value_too_large, boost::system::system_category()});
387 if (responseSize == 0)
401 boost::asio::transfer_all(),
405 std::placeholders::_1,
406 std::placeholders::_2));
426 JLOG(
j_.
trace()) <<
"Complete.";
441 boost::system::error_code
const& ecResult,
445 boost::system::error_code ecCancel;
450 catch (boost::system::system_error
const& e)
452 JLOG(
j_.
trace()) <<
"invokeComplete: Deadline cancel error: " << e.what();
490 boost::asio::ip::resolver_query_base::flags
flags;
503 bool(boost::system::error_code
const& ecResult,
int iStatus,
std::string const& strData)>
506 boost::asio::basic_waitable_timer<std::chrono::steady_clock>
mDeadline;
521 boost::asio::io_context& io_context,
523 unsigned short const port,
528 bool(boost::system::error_code
const& ecResult,
int iStatus,
std::string const& strData)>
533 client->get(bSSL, deqSites, strPath, timeout, complete);
539 boost::asio::io_context& io_context,
541 unsigned short const port,
546 bool(boost::system::error_code
const& ecResult,
int iStatus,
std::string const& strData)>
553 client->get(bSSL, deqSites, strPath, timeout, complete);
559 boost::asio::io_context& io_context,
561 unsigned short const port,
566 bool(boost::system::error_code
const& ecResult,
int iStatus,
std::string const& strData)>
573 client->request(bSSL, deqSites, setRequest, timeout, complete);
void async_handshake(handshake_type type, callback cbFunc)
void async_write(Buf const &buffers, Handler handler)
lowest_layer_type & lowest_layer()
void async_read_until(Seq const &buffers, Condition condition, Handler handler)
void async_read(Buf const &buffers, Condition cond, Handler handler)
void async_shutdown(ShutdownHandler handler)
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
void handleDeadline(boost::system::error_code const &ecResult)
void handleWrite(boost::system::error_code const &ecResult, std::size_t bytes_transferred)
std::size_t const maxResponseSize_
boost::system::error_code mShutdown
void request(bool bSSL, std::deque< std::string > deqSites, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete)
void handleConnect(boost::system::error_code const &ecResult)
std::deque< std::string > mDeqSites
boost::asio::basic_waitable_timer< std::chrono::steady_clock > mDeadline
boost::asio::streambuf mRequest
void makeGet(std::string const &strPath, boost::asio::streambuf &sb, std::string const &strHost)
void handleResolve(boost::system::error_code const &ecResult, boost::asio::ip::tcp::resolver::results_type result)
void handleRequest(boost::system::error_code const &ecResult)
boost::asio::streambuf mHeader
boost::asio::streambuf mResponse
unsigned short const mPort
void handleHeader(boost::system::error_code const &ecResult, std::size_t bytes_transferred)
void get(bool bSSL, std::deque< std::string > deqSites, std::string const &strPath, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete)
std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> mComplete
std::chrono::seconds mTimeout
std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> mBuild
void handleData(boost::system::error_code const &ecResult, std::size_t bytes_transferred)
HTTPClientImp(boost::asio::io_context &io_context, unsigned short const port, std::size_t maxResponseSize, beast::Journal &j)
void invokeComplete(boost::system::error_code const &ecResult, int iStatus=0, std::string const &strData="")
void handleShutdown(boost::system::error_code const &ecResult)
boost::asio::ip::tcp::resolver mResolver
std::shared_ptr< Query > mQuery
Provides an asynchronous HTTP client implementation with optional SSL.
static void initializeSSLContext(std::string const &sslVerifyDir, std::string const &sslVerifyFile, bool sslVerify, beast::Journal j)
static void get(bool bSSL, boost::asio::io_context &io_context, std::deque< std::string > deqSites, unsigned short const port, std::string const &strPath, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
static void request(bool bSSL, boost::asio::io_context &io_context, std::string strSite, unsigned short const port, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(boost::system::error_code const &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
static constexpr auto maxClientHeaderBytes
static void cleanupSSLContext()
Destroys the global SSL context created by initializeSSLContext().
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static std::optional< HTTPClientSSLContext > httpClientSSLContext
T shared_from_this(T... args)
boost::asio::ip::resolver_query_base::flags flags