mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Make HttpsClient more flexable and easier to use.
This commit is contained in:
@@ -16,34 +16,38 @@ using namespace boost::asio;
|
|||||||
|
|
||||||
HttpsClient::HttpsClient(
|
HttpsClient::HttpsClient(
|
||||||
boost::asio::io_service& io_service,
|
boost::asio::io_service& io_service,
|
||||||
const std::string strDomain,
|
const unsigned short port,
|
||||||
const std::string strPath,
|
const std::string strPath,
|
||||||
unsigned short port,
|
|
||||||
std::size_t responseMax
|
std::size_t responseMax
|
||||||
) :
|
) :
|
||||||
mCtx(boost::asio::ssl::context::sslv23),
|
mCtx(boost::asio::ssl::context::sslv23),
|
||||||
mResolver(io_service),
|
mResolver(io_service),
|
||||||
mQuery(strDomain, boost::lexical_cast<std::string>(port),
|
|
||||||
ip::resolver_query_base::numeric_service|ip::resolver_query_base::numeric_service),
|
|
||||||
mSocketSsl(io_service, mCtx),
|
mSocketSsl(io_service, mCtx),
|
||||||
mResponse(responseMax),
|
mResponse(responseMax),
|
||||||
mStrDomain(strDomain),
|
mStrPath(strPath),
|
||||||
|
mPort(port),
|
||||||
mDeadline(io_service)
|
mDeadline(io_service)
|
||||||
{
|
{
|
||||||
std::ostream osRequest(&mRequest);
|
|
||||||
|
|
||||||
osRequest <<
|
|
||||||
"GET " << strPath << " HTTP/1.0\r\n"
|
|
||||||
"Host: " << mStrDomain << "\r\n"
|
|
||||||
"Accept: */*\r\n" // YYY Do we need this line?
|
|
||||||
"Connection: close\r\n\r\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpsClient::httpsGet(
|
void HttpsClient::httpsGet(
|
||||||
|
std::deque<std::string> deqSites,
|
||||||
boost::posix_time::time_duration timeout,
|
boost::posix_time::time_duration timeout,
|
||||||
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
|
||||||
|
|
||||||
|
mDeqSites = deqSites;
|
||||||
mComplete = complete;
|
mComplete = complete;
|
||||||
|
mTimeout = timeout;
|
||||||
|
|
||||||
|
httpsNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpsClient::httpsNext()
|
||||||
|
{
|
||||||
|
std::cerr << "Fetch: " << mDeqSites[0] << std::endl;
|
||||||
|
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> query(new boost::asio::ip::tcp::resolver::query(mDeqSites[0], boost::lexical_cast<std::string>(mPort),
|
||||||
|
ip::resolver_query_base::numeric_service|ip::resolver_query_base::numeric_service));
|
||||||
|
mQuery = query;
|
||||||
|
|
||||||
mCtx.set_default_verify_paths(mShutdown);
|
mCtx.set_default_verify_paths(mShutdown);
|
||||||
if (!mShutdown)
|
if (!mShutdown)
|
||||||
@@ -53,7 +57,7 @@ void HttpsClient::httpsGet(
|
|||||||
|
|
||||||
if (!mShutdown)
|
if (!mShutdown)
|
||||||
{
|
{
|
||||||
mDeadline.expires_from_now(timeout, mShutdown);
|
mDeadline.expires_from_now(mTimeout, mShutdown);
|
||||||
|
|
||||||
std::cerr << "expires_from_now: " << mShutdown.message() << std::endl;
|
std::cerr << "expires_from_now: " << mShutdown.message() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -69,9 +73,9 @@ void HttpsClient::httpsGet(
|
|||||||
|
|
||||||
if (!mShutdown)
|
if (!mShutdown)
|
||||||
{
|
{
|
||||||
std::cerr << "Resolving: " << mStrDomain << std::endl;
|
std::cerr << "Resolving: " << mDeqSites[0] << std::endl;
|
||||||
|
|
||||||
mResolver.async_resolve(mQuery,
|
mResolver.async_resolve(*mQuery,
|
||||||
boost::bind(
|
boost::bind(
|
||||||
&HttpsClient::handleResolve,
|
&HttpsClient::handleResolve,
|
||||||
shared_from_this(),
|
shared_from_this(),
|
||||||
@@ -90,11 +94,11 @@ void HttpsClient::handleDeadline(const boost::system::error_code& ecResult)
|
|||||||
// Timer canceled because deadline no longer needed.
|
// Timer canceled because deadline no longer needed.
|
||||||
std::cerr << "Deadline cancelled." << std::endl;
|
std::cerr << "Deadline cancelled." << std::endl;
|
||||||
|
|
||||||
// Do nothing.
|
// Do nothing. Aborter is done.
|
||||||
}
|
}
|
||||||
else if (ecResult)
|
else if (ecResult)
|
||||||
{
|
{
|
||||||
std::cerr << "Deadline error: " << mStrDomain << ": " << ecResult.message() << std::endl;
|
std::cerr << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message() << std::endl;
|
||||||
|
|
||||||
// Can't do anything sound.
|
// Can't do anything sound.
|
||||||
abort();
|
abort();
|
||||||
@@ -117,7 +121,7 @@ void HttpsClient::handleDeadline(const boost::system::error_code& ecResult)
|
|||||||
|
|
||||||
if (ec_shutdown)
|
if (ec_shutdown)
|
||||||
{
|
{
|
||||||
std::cerr << "Shutdown error: " << mStrDomain << ": " << ec_shutdown.message() << std::endl;
|
std::cerr << "Shutdown error: " << mDeqSites[0] << ": " << ec_shutdown.message() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +136,7 @@ void HttpsClient::handleResolve(
|
|||||||
|
|
||||||
if (mShutdown)
|
if (mShutdown)
|
||||||
{
|
{
|
||||||
std::cerr << "Resolve error: " << mStrDomain << ": " << mShutdown.message() << std::endl;
|
std::cerr << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message() << std::endl;
|
||||||
|
|
||||||
invokeComplete(mShutdown);
|
invokeComplete(mShutdown);
|
||||||
}
|
}
|
||||||
@@ -168,11 +172,11 @@ void HttpsClient::handleConnect(const boost::system::error_code& ecResult)
|
|||||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
|
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||||
|
|
||||||
// XXX Verify semantics of RFC 2818 are what we want.
|
// XXX Verify semantics of RFC 2818 are what we want.
|
||||||
mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mStrDomain), mShutdown);
|
mSocketSsl.set_verify_callback(boost::asio::ssl::rfc2818_verification(mDeqSites[0]), mShutdown);
|
||||||
|
|
||||||
if (mShutdown)
|
if (mShutdown)
|
||||||
{
|
{
|
||||||
std::cerr << "set_verify_callback: " << mStrDomain << ": " << mShutdown.message() << std::endl;
|
std::cerr << "set_verify_callback: " << mDeqSites[0] << ": " << mShutdown.message() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +208,14 @@ void HttpsClient::handleRequest(const boost::system::error_code& ecResult)
|
|||||||
{
|
{
|
||||||
std::cerr << "SSL session started." << std::endl;
|
std::cerr << "SSL session started." << std::endl;
|
||||||
|
|
||||||
|
std::ostream osRequest(&mRequest);
|
||||||
|
|
||||||
|
osRequest <<
|
||||||
|
"GET " << mStrPath << " HTTP/1.0\r\n"
|
||||||
|
"Host: " << mDeqSites[0] << "\r\n"
|
||||||
|
"Accept: */*\r\n" // YYY Do we need this line?
|
||||||
|
"Connection: close\r\n\r\n";
|
||||||
|
|
||||||
boost::asio::async_write(
|
boost::asio::async_write(
|
||||||
mSocketSsl,
|
mSocketSsl,
|
||||||
mRequest,
|
mRequest,
|
||||||
@@ -277,7 +289,16 @@ void HttpsClient::invokeComplete(const boost::system::error_code& ecResult, std:
|
|||||||
std::cerr << "Deadline cancel error: " << ecCancel.message() << std::endl;
|
std::cerr << "Deadline cancel error: " << ecCancel.message() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComplete(ecResult ? ecResult : ecCancel, strData);
|
mDeqSites.pop_front();
|
||||||
|
|
||||||
|
if (mDeqSites.empty())
|
||||||
|
{
|
||||||
|
mComplete(ecResult ? ecResult : ecCancel, strData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpsNext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpsClient::parseData()
|
void HttpsClient::parseData()
|
||||||
@@ -293,8 +314,9 @@ void HttpsClient::parseData()
|
|||||||
&& !smMatch[1].compare("200")
|
&& !smMatch[1].compare("200")
|
||||||
&& boost::regex_match(strData, smMatch, reBody); // Match body.
|
&& boost::regex_match(strData, smMatch, reBody); // Match body.
|
||||||
|
|
||||||
std::cerr << "Match: " << bMatch << std::endl;
|
// std::cerr << "Data:" << strData << std::endl;
|
||||||
std::cerr << "Body:" << smMatch[1] << std::endl;
|
// std::cerr << "Match: " << bMatch << std::endl;
|
||||||
|
// std::cerr << "Body:" << smMatch[1] << std::endl;
|
||||||
|
|
||||||
if (bMatch)
|
if (bMatch)
|
||||||
{
|
{
|
||||||
@@ -308,4 +330,52 @@ void HttpsClient::parseData()
|
|||||||
invokeComplete(boost::system::error_code(errc::bad_address, system_category()));
|
invokeComplete(boost::system::error_code(errc::bad_address, system_category()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpsClient::httpsGet(
|
||||||
|
boost::asio::io_service& io_service,
|
||||||
|
std::deque<std::string> deqSites,
|
||||||
|
const unsigned short port,
|
||||||
|
const std::string strPath,
|
||||||
|
std::size_t responseMax,
|
||||||
|
boost::posix_time::time_duration timeout,
|
||||||
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
|
||||||
|
|
||||||
|
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, strPath, responseMax));
|
||||||
|
|
||||||
|
client->httpsGet(deqSites, timeout, complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpsClient::httpsGet(
|
||||||
|
boost::asio::io_service& io_service,
|
||||||
|
std::string strSite,
|
||||||
|
const unsigned short port,
|
||||||
|
const std::string strPath,
|
||||||
|
std::size_t responseMax,
|
||||||
|
boost::posix_time::time_duration timeout,
|
||||||
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete) {
|
||||||
|
|
||||||
|
std::deque<std::string> deqSites(1, strSite);
|
||||||
|
|
||||||
|
boost::shared_ptr<HttpsClient> client(new HttpsClient(io_service, port, strPath, responseMax));
|
||||||
|
|
||||||
|
client->httpsGet(deqSites, timeout, complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HttpsClient::httpsParseUrl(const std::string strUrl, std::string& strDomain, std::string& strPath)
|
||||||
|
{
|
||||||
|
static boost::regex reUrl("(?i)\\`https://([^/]+)(/.*)\\'"); // https://DOMAINPATH
|
||||||
|
|
||||||
|
boost::smatch smMatch;
|
||||||
|
|
||||||
|
bool bMatch = boost::regex_match(strUrl, smMatch, reUrl); // Match status code.
|
||||||
|
|
||||||
|
if (bMatch)
|
||||||
|
{
|
||||||
|
strDomain = smMatch[0];
|
||||||
|
strDomain = smMatch[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return bMatch;
|
||||||
|
}
|
||||||
|
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef _HTTPS_CLIENT_
|
#ifndef _HTTPS_CLIENT_
|
||||||
#define _HTTPS_CLIENT_
|
#define _HTTPS_CLIENT_
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
@@ -18,19 +19,23 @@
|
|||||||
class HttpsClient : public boost::enable_shared_from_this<HttpsClient>
|
class HttpsClient : public boost::enable_shared_from_this<HttpsClient>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
boost::asio::ssl::context mCtx;
|
boost::asio::ssl::context mCtx;
|
||||||
boost::asio::ip::tcp::resolver mResolver;
|
boost::asio::ip::tcp::resolver mResolver;
|
||||||
boost::asio::ip::tcp::resolver::query mQuery;
|
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> mQuery;
|
||||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
|
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
|
||||||
boost::asio::streambuf mRequest;
|
boost::asio::streambuf mRequest;
|
||||||
boost::asio::streambuf mResponse;
|
boost::asio::streambuf mResponse;
|
||||||
std::string mStrDomain;
|
const std::string mStrPath;
|
||||||
|
const unsigned short mPort;
|
||||||
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> mComplete;
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> mComplete;
|
||||||
|
|
||||||
boost::asio::deadline_timer mDeadline;
|
boost::asio::deadline_timer mDeadline;
|
||||||
|
|
||||||
// If not success, we are shutting down.
|
// If not success, we are shutting down.
|
||||||
boost::system::error_code mShutdown;
|
boost::system::error_code mShutdown;
|
||||||
|
|
||||||
|
std::deque<std::string> mDeqSites;
|
||||||
|
boost::posix_time::time_duration mTimeout;
|
||||||
|
|
||||||
void handleDeadline(const boost::system::error_code& ecResult);
|
void handleDeadline(const boost::system::error_code& ecResult);
|
||||||
|
|
||||||
@@ -44,23 +49,44 @@ private:
|
|||||||
void handleWrite(const boost::system::error_code& ecResult);
|
void handleWrite(const boost::system::error_code& ecResult);
|
||||||
void handleData(const boost::system::error_code& ecResult);
|
void handleData(const boost::system::error_code& ecResult);
|
||||||
|
|
||||||
void invokeComplete(const boost::system::error_code& ecResult, std::string strData = "");
|
|
||||||
|
|
||||||
void parseData();
|
void parseData();
|
||||||
|
void httpsNext();
|
||||||
|
|
||||||
|
void invokeComplete(const boost::system::error_code& ecResult, std::string strData = "");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HttpsClient(
|
HttpsClient(
|
||||||
boost::asio::io_service& io_service,
|
boost::asio::io_service& io_service,
|
||||||
const std::string strDomain,
|
const unsigned short port,
|
||||||
const std::string strPath,
|
const std::string strPath,
|
||||||
unsigned short port,
|
|
||||||
std::size_t responseMax
|
std::size_t responseMax
|
||||||
);
|
);
|
||||||
|
|
||||||
void httpsGet(
|
void httpsGet(
|
||||||
|
std::deque<std::string> deqSites,
|
||||||
boost::posix_time::time_duration timeout,
|
boost::posix_time::time_duration timeout,
|
||||||
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
|
||||||
|
|
||||||
|
static void httpsGet(
|
||||||
|
boost::asio::io_service& io_service,
|
||||||
|
std::deque<std::string> deqSites,
|
||||||
|
const unsigned short port,
|
||||||
|
const std::string strPath,
|
||||||
|
std::size_t responseMax,
|
||||||
|
boost::posix_time::time_duration timeout,
|
||||||
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
|
||||||
|
|
||||||
|
static void httpsGet(
|
||||||
|
boost::asio::io_service& io_service,
|
||||||
|
std::string strSite,
|
||||||
|
const unsigned short port,
|
||||||
|
const std::string strPath,
|
||||||
|
std::size_t responseMax,
|
||||||
|
boost::posix_time::time_duration timeout,
|
||||||
|
boost::function<void(const boost::system::error_code& ecResult, std::string& strData)> complete);
|
||||||
|
|
||||||
|
static bool httpsParseUrl(const std::string strUrl, std::string& strDomain, std::string& strPath);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
Reference in New Issue
Block a user