2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/HTTPCommon.h>
|
2016-12-30 20:52:56 +00:00
|
|
|
|
2018-06-14 21:20:39 +00:00
|
|
|
#include <Common/DNSResolver.h>
|
|
|
|
#include <Common/Exception.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/config.h>
|
2018-07-10 17:40:17 +00:00
|
|
|
#include <Poco/Version.h>
|
2018-05-14 18:36:01 +00:00
|
|
|
#if USE_POCO_NETSSL
|
2017-02-27 21:07:57 +00:00
|
|
|
#include <Poco/Net/AcceptCertificateHandler.h>
|
|
|
|
#include <Poco/Net/Context.h>
|
2018-06-14 21:20:39 +00:00
|
|
|
#include <Poco/Net/HTTPSClientSession.h>
|
2017-02-27 21:07:57 +00:00
|
|
|
#include <Poco/Net/InvalidCertificateHandler.h>
|
|
|
|
#include <Poco/Net/PrivateKeyPassphraseHandler.h>
|
|
|
|
#include <Poco/Net/RejectCertificateHandler.h>
|
|
|
|
#include <Poco/Net/SSLManager.h>
|
2017-03-28 20:30:57 +00:00
|
|
|
#endif
|
|
|
|
#include <Poco/Net/HTTPServerResponse.h>
|
2017-02-27 21:07:57 +00:00
|
|
|
#include <Poco/Util/Application.h>
|
2017-01-30 05:13:58 +00:00
|
|
|
|
2018-06-15 07:42:57 +00:00
|
|
|
#include <sstream>
|
2016-12-30 20:52:56 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2018-06-16 05:54:06 +00:00
|
|
|
|
2018-06-14 21:20:39 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int RECEIVED_ERROR_FROM_REMOTE_IO_SERVER;
|
|
|
|
extern const int RECEIVED_ERROR_TOO_MANY_REQUESTS;
|
2018-06-16 05:54:06 +00:00
|
|
|
extern const int FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME;
|
2018-06-14 21:20:39 +00:00
|
|
|
}
|
|
|
|
|
2018-06-16 05:54:06 +00:00
|
|
|
|
2017-09-08 16:41:35 +00:00
|
|
|
void setResponseDefaultHeaders(Poco::Net::HTTPServerResponse & response, unsigned keep_alive_timeout)
|
2016-12-31 02:05:37 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (!response.getKeepAlive())
|
|
|
|
return;
|
2016-12-30 20:52:56 +00:00
|
|
|
|
2017-09-08 11:57:43 +00:00
|
|
|
Poco::Timespan timeout(keep_alive_timeout, 0);
|
|
|
|
if (timeout.totalSeconds())
|
|
|
|
response.set("Keep-Alive", "timeout=" + std::to_string(timeout.totalSeconds()));
|
2016-12-30 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
2017-02-27 21:07:57 +00:00
|
|
|
|
2018-06-16 05:54:06 +00:00
|
|
|
void initSSL()
|
2017-02-27 21:07:57 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
// http://stackoverflow.com/questions/18315472/https-request-in-c-using-poco
|
2018-05-14 18:36:01 +00:00
|
|
|
#if USE_POCO_NETSSL
|
2018-06-16 05:54:06 +00:00
|
|
|
struct Initializer
|
|
|
|
{
|
|
|
|
Initializer()
|
|
|
|
{
|
|
|
|
Poco::Net::initializeSSL();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static Initializer initializer;
|
2017-03-28 20:30:57 +00:00
|
|
|
#endif
|
2017-02-27 21:07:57 +00:00
|
|
|
}
|
2018-06-14 21:20:39 +00:00
|
|
|
|
|
|
|
|
2018-06-16 05:54:06 +00:00
|
|
|
std::unique_ptr<Poco::Net::HTTPClientSession> makeHTTPSession(const Poco::URI & uri, const ConnectionTimeouts & timeouts)
|
2018-06-14 21:20:39 +00:00
|
|
|
{
|
|
|
|
bool is_ssl = static_cast<bool>(uri.getScheme() == "https");
|
2018-06-16 05:54:06 +00:00
|
|
|
std::unique_ptr<Poco::Net::HTTPClientSession> session;
|
|
|
|
|
|
|
|
if (is_ssl)
|
2018-06-14 21:20:39 +00:00
|
|
|
#if USE_POCO_NETSSL
|
2018-06-16 05:54:06 +00:00
|
|
|
session = std::make_unique<Poco::Net::HTTPSClientSession>();
|
|
|
|
#else
|
|
|
|
throw Exception("ClickHouse was built without HTTPS support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME);
|
2018-06-14 21:20:39 +00:00
|
|
|
#endif
|
2018-06-16 05:54:06 +00:00
|
|
|
else
|
|
|
|
session = std::make_unique<Poco::Net::HTTPClientSession>();
|
2018-06-14 21:20:39 +00:00
|
|
|
|
|
|
|
session->setHost(DNSResolver::instance().resolveHost(uri.getHost()).toString());
|
|
|
|
session->setPort(uri.getPort());
|
|
|
|
|
|
|
|
#if POCO_CLICKHOUSE_PATCH || POCO_VERSION >= 0x02000000
|
|
|
|
session->setTimeout(timeouts.connection_timeout, timeouts.send_timeout, timeouts.receive_timeout);
|
|
|
|
#else
|
2018-07-10 17:40:17 +00:00
|
|
|
session->setTimeout(std::max({timeouts.connection_timeout, timeouts.send_timeout, timeouts.receive_timeout}));
|
2018-06-14 21:20:39 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-16 05:54:06 +00:00
|
|
|
std::istream * receiveResponse(
|
2018-06-14 21:20:39 +00:00
|
|
|
Poco::Net::HTTPClientSession & session, const Poco::Net::HTTPRequest & request, Poco::Net::HTTPResponse & response)
|
|
|
|
{
|
|
|
|
auto istr = &session.receiveResponse(response);
|
|
|
|
auto status = response.getStatus();
|
|
|
|
|
|
|
|
if (status != Poco::Net::HTTPResponse::HTTP_OK)
|
|
|
|
{
|
|
|
|
std::stringstream error_message;
|
|
|
|
error_message << "Received error from remote server " << request.getURI() << ". HTTP status code: " << status << " "
|
|
|
|
<< response.getReason() << ", body: " << istr->rdbuf();
|
|
|
|
|
|
|
|
throw Exception(error_message.str(),
|
|
|
|
status == HTTP_TOO_MANY_REQUESTS ? ErrorCodes::RECEIVED_ERROR_TOO_MANY_REQUESTS
|
|
|
|
: ErrorCodes::RECEIVED_ERROR_FROM_REMOTE_IO_SERVER);
|
|
|
|
}
|
|
|
|
return istr;
|
|
|
|
}
|
2018-06-16 05:54:06 +00:00
|
|
|
|
2016-12-30 20:52:56 +00:00
|
|
|
}
|