20#include <xrpld/net/AutoSocket.h>
21#include <xrpld/net/HTTPClient.h>
22#include <xrpld/net/HTTPClientSSLContext.h>
24#include <xrpl/basics/Log.h>
25#include <xrpl/beast/core/LexicalCast.h>
27#include <boost/asio.hpp>
28#include <boost/asio/ip/tcp.hpp>
29#include <boost/asio/ssl.hpp>
30#include <boost/regex.hpp>
55 boost::asio::io_service& io_service,
56 const unsigned short port,
74 boost::asio::streambuf& sb,
79 osRequest <<
"GET " << strPath
85 "Connection: close\r\n\r\n";
95 void(boost::asio::streambuf& sb,
std::string const& strHost)> build,
98 const boost::system::error_code& ecResult,
119 const boost::system::error_code& ecResult,
133 std::placeholders::_1,
134 std::placeholders::_2),
146 auto query = std::make_shared<boost::asio::ip::tcp::resolver::query>(
149 boost::asio::ip::resolver_query_base::numeric_service);
161 std::placeholders::_1));
173 std::placeholders::_1,
174 std::placeholders::_2));
184 if (ecResult == boost::asio::error::operation_aborted)
187 JLOG(
j_.
trace()) <<
"Deadline cancelled.";
194 << ecResult.message();
201 JLOG(
j_.
trace()) <<
"Deadline arrived.";
206 boost::system::errc::bad_address,
207 boost::system::system_category()};
216 std::placeholders::_1));
226 << ecResult.message();
232 const boost::system::error_code& ecResult,
233 boost::asio::ip::tcp::resolver::iterator itrEndpoint)
251 JLOG(
j_.
trace()) <<
"Resolve complete.";
253 boost::asio::async_connect(
259 std::placeholders::_1));
276 JLOG(
j_.
trace()) <<
"Connected.";
295 AutoSocket::ssl_socket::client,
299 std::placeholders::_1));
321 JLOG(
j_.
trace()) <<
"Session started.";
330 std::placeholders::_1,
331 std::placeholders::_2));
337 const boost::system::error_code& ecResult,
359 std::placeholders::_1,
360 std::placeholders::_2));
366 const boost::system::error_code& ecResult,
372 JLOG(
j_.
trace()) <<
"Header: \"" << strHeader <<
"\"";
374 static boost::regex reStatus{
375 "\\`HTTP/1\\S+ (\\d{3}) .*\\'"};
376 static boost::regex reSize{
377 "\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'"};
378 static boost::regex reBody{
"\\`.*\\r\\n\\r\\n(.*)\\'"};
380 boost::smatch smMatch;
382 if (!boost::regex_match(strHeader, smMatch, reStatus))
385 JLOG(
j_.
trace()) <<
"No status code";
387 boost::system::errc::bad_address,
388 boost::system::system_category()});
394 if (boost::regex_match(strHeader, smMatch, reBody))
398 if (boost::regex_match(strHeader, smMatch, reSize))
399 return beast::lexicalCast<std::size_t>(
406 JLOG(
j_.
trace()) <<
"Response field too large";
408 boost::system::errc::value_too_large,
409 boost::system::system_category()});
413 if (responseSize == 0)
427 boost::asio::transfer_all(),
431 std::placeholders::_1,
432 std::placeholders::_2));
438 const boost::system::error_code& ecResult,
454 JLOG(
j_.
trace()) <<
"Complete.";
470 const boost::system::error_code& ecResult,
474 boost::system::error_code ecCancel;
480 JLOG(
j_.
trace()) <<
"invokeComplete: Deadline cancel error: "
481 << ecCancel.message();
484 JLOG(
j_.
debug()) <<
"invokeComplete: Deadline popping: "
500 mComplete(ecResult ? ecResult : ecCancel, iStatus, strData);
526 const boost::system::error_code& ecResult,
531 boost::asio::basic_waitable_timer<std::chrono::steady_clock>
mDeadline;
546 boost::asio::io_service& io_service,
548 const unsigned short port,
553 const boost::system::error_code& ecResult,
559 std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
560 client->get(bSSL, deqSites, strPath, timeout, complete);
566 boost::asio::io_service& io_service,
568 const unsigned short port,
573 const boost::system::error_code& ecResult,
581 std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
582 client->get(bSSL, deqSites, strPath, timeout, complete);
588 boost::asio::io_service& io_service,
590 const unsigned short port,
596 const boost::system::error_code& ecResult,
604 std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
605 client->request(bSSL, deqSites, setRequest, timeout, complete);
void async_handshake(handshake_type type, callback cbFunc)
void async_read_until(const Seq &buffers, Condition condition, Handler handler)
lowest_layer_type & lowest_layer()
void async_write(const Buf &buffers, Handler handler)
void async_read(const Buf &buffers, Condition cond, Handler handler)
void async_shutdown(ShutdownHandler handler)
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
void handleWrite(const boost::system::error_code &ecResult, std::size_t bytes_transferred)
void handleConnect(const boost::system::error_code &ecResult)
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(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> complete)
void makeGet(std::string const &strPath, boost::asio::streambuf &sb, std::string const &strHost)
void handleRequest(const boost::system::error_code &ecResult)
void get(bool bSSL, std::deque< std::string > deqSites, std::string const &strPath, std::chrono::seconds timeout, std::function< bool(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> complete)
void invokeComplete(const boost::system::error_code &ecResult, int iStatus=0, std::string const &strData="")
void handleDeadline(const boost::system::error_code &ecResult)
void handleResolve(const boost::system::error_code &ecResult, boost::asio::ip::tcp::resolver::iterator itrEndpoint)
std::chrono::seconds mTimeout
void handleShutdown(const boost::system::error_code &ecResult)
std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> mBuild
std::size_t const maxResponseSize_
std::shared_ptr< boost::asio::ip::tcp::resolver::query > mQuery
boost::asio::streambuf mHeader
boost::asio::ip::tcp::resolver mResolver
boost::asio::streambuf mRequest
boost::asio::basic_waitable_timer< std::chrono::steady_clock > mDeadline
std::deque< std::string > mDeqSites
void handleHeader(const boost::system::error_code &ecResult, std::size_t bytes_transferred)
void handleData(const boost::system::error_code &ecResult, std::size_t bytes_transferred)
boost::asio::streambuf mResponse
const unsigned short mPort
boost::system::error_code mShutdown
std::function< bool(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> mComplete
HTTPClientImp(boost::asio::io_service &io_service, const unsigned short port, std::size_t maxResponseSize, beast::Journal &j)
Provides an asynchronous HTTP client implementation with optional SSL.
static void initializeSSLContext(Config const &config, beast::Journal j)
static void request(bool bSSL, boost::asio::io_service &io_service, std::string strSite, const unsigned short port, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
static void get(bool bSSL, boost::asio::io_service &io_service, std::deque< std::string > deqSites, const unsigned short port, std::string const &strPath, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
static constexpr auto maxClientHeaderBytes
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)