提交 835dc4c4 编写于 作者: Z zhang2014

After merge upsream master fix

上级 1eda48b4
......@@ -18,9 +18,9 @@ namespace ErrorCodes
}
HTTPInputStreams::HTTPInputStreams(Context & context, HTTPServerRequest & request, HTMLForm & from)
: in(createRawInBuffer(request))
, in_maybe_compressed(createCompressedBuffer(request, in))
, in_maybe_internal_compressed(createInternalCompressedBuffer(from, in_maybe_compressed))
: in(plainBuffer(request))
, in_maybe_compressed(compressedBuffer(request, in))
, in_maybe_internal_compressed(internalCompressedBuffer(from, in_maybe_compressed))
{
/// If 'http_native_compression_disable_checksumming_on_decompress' setting is turned on,
/// checksums of client data compressed with internal algorithm are not checked.
......@@ -31,12 +31,12 @@ HTTPInputStreams::HTTPInputStreams(Context & context, HTTPServerRequest & reques
}
}
std::unique_ptr<ReadBuffer> HTTPInputStreams::createRawInBuffer(HTTPServerRequest & request) const
std::unique_ptr<ReadBuffer> HTTPInputStreams::plainBuffer(HTTPServerRequest & request) const
{
return std::make_unique<ReadBufferFromIStream>(request.stream());
}
std::unique_ptr<ReadBuffer> HTTPInputStreams::createCompressedBuffer(HTTPServerRequest & request, std::unique_ptr<ReadBuffer> & raw_buffer) const
std::unique_ptr<ReadBuffer> HTTPInputStreams::compressedBuffer(HTTPServerRequest & request, std::unique_ptr<ReadBuffer> & plain_buffer) const
{
/// Request body can be compressed using algorithm specified in the Content-Encoding header.
String http_compressed_method = request.get("Content-Encoding", "");
......@@ -44,22 +44,22 @@ std::unique_ptr<ReadBuffer> HTTPInputStreams::createCompressedBuffer(HTTPServerR
if (!http_compressed_method.empty())
{
if (http_compressed_method == "gzip")
return std::make_unique<ZlibInflatingReadBuffer>(std::move(raw_buffer), CompressionMethod::Gzip);
return std::make_unique<ZlibInflatingReadBuffer>(std::move(plain_buffer), CompressionMethod::Gzip);
else if (http_compressed_method == "deflate")
return std::make_unique<ZlibInflatingReadBuffer>(std::move(raw_buffer), CompressionMethod::Zlib);
return std::make_unique<ZlibInflatingReadBuffer>(std::move(plain_buffer), CompressionMethod::Zlib);
#if USE_BROTLI
else if (http_compressed_method == "br")
return std::make_unique<BrotliReadBuffer>(std::move(raw_buffer));
return std::make_unique<BrotliReadBuffer>(std::move(plain_buffer));
#endif
else
throw Exception("Unknown Content-Encoding of HTTP request: " + http_compressed_method, ErrorCodes::UNKNOWN_COMPRESSION_METHOD);
}
return std::move(raw_buffer);
return std::move(plain_buffer);
}
std::unique_ptr<ReadBuffer> HTTPInputStreams::createInternalCompressedBuffer(
HTMLForm & params, std::unique_ptr<ReadBuffer> & http_maybe_encoding_buffer) const
std::unique_ptr<ReadBuffer> HTTPInputStreams::internalCompressedBuffer(
HTMLForm &params, std::unique_ptr<ReadBuffer> &http_maybe_encoding_buffer) const
{
/// The data can also be compressed using incompatible internal algorithm. This is indicated by
/// 'decompress' query parameter.
......
......@@ -21,9 +21,9 @@ struct HTTPInputStreams
HTTPInputStreams(Context & context, HTTPServerRequest & request, HTMLForm & from);
ReadBufferUniquePtr createRawInBuffer(HTTPServerRequest & request) const;
ReadBufferUniquePtr createCompressedBuffer(HTTPServerRequest & request, ReadBufferUniquePtr & raw_buffer) const;
ReadBufferUniquePtr createInternalCompressedBuffer(HTMLForm & params, ReadBufferUniquePtr & http_maybe_encoding_buffer) const;
ReadBufferUniquePtr plainBuffer(HTTPServerRequest & request) const;
ReadBufferUniquePtr compressedBuffer(HTTPServerRequest & request, ReadBufferUniquePtr & plain_buffer) const;
ReadBufferUniquePtr internalCompressedBuffer(HTMLForm & params, ReadBufferUniquePtr & http_maybe_encoding_buffer) const;
};
}
#include "HTTPHandlerFactory.h"
#include "NotFoundHandler.h"
#include "HTTPRequestHandler/HTTPRootRequestHandler.h"
#include "HTTPRequestHandler/HTTPPingRequestHandler.h"
#include "HTTPRequestHandler/HTTPReplicasStatusRequestHandler.h"
namespace DB
{
namespace ErrorCodes
{
extern const int SYNTAX_ERROR;
extern const int UNKNOWN_HTTP_HANDLER_TYPE;
extern const int EMPTY_HTTP_HANDLER_IN_CONFIG;
}
InterserverIOHTTPHandlerFactory::InterserverIOHTTPHandlerFactory(IServer & server_, const std::string & name_)
: server(server_), log(&Logger::get(name_)), name(name_)
{
}
Poco::Net::HTTPRequestHandler * InterserverIOHTTPHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & request)
{
LOG_TRACE(log, "HTTP Request for " << name << ". "
<< "Method: " << request.getMethod()
<< ", Address: " << request.clientAddress().toString()
<< ", User-Agent: " << (request.has("User-Agent") ? request.get("User-Agent") : "none")
<< (request.hasContentLength() ? (", Length: " + std::to_string(request.getContentLength())) : (""))
<< ", Content Type: " << request.getContentType()
<< ", Transfer Encoding: " << request.getTransferEncoding());
const auto & uri = request.getURI();
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD)
{
if (uri == "/")
return new HTTPRootRequestHandler(server);
if (uri == "/ping")
return new HTTPPingRequestHandler(server);
else if (startsWith(uri, "/replicas_status"))
return new HTTPReplicasStatusRequestHandler(server.context());
}
if (uri.find('?') != std::string::npos || request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
{
return new InterserverIOHTTPHandler(server);
}
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
{
return new NotFoundHandler(
"Use / or /ping for health checks.\n"
"Or /replicas_status for more sophisticated health checks.\n"
"Send queries from your program with POST method or GET /?query=...\n\n"
" Use clickhouse-client:\n\n"
" For interactive data analysis:\n"
" clickhouse-client\n\n"
" For batch query processing:\n"
" clickhouse-client --query='SELECT 1' > result\n"
" clickhouse-client < query > result"
);
}
return nullptr;
}
HTTPHandlerFactory::HTTPHandlerFactory(IServer & server_, const std::string & name_)
: server(server_), log(&Logger::get(name_)), name(name_)
{
updateHTTPHandlersCreator(server.config());
if (handlers_creator.empty())
throw Exception("The HTTPHandlers does not exist in the config.xml", ErrorCodes::EMPTY_HTTP_HANDLER_IN_CONFIG);
}
Poco::Net::HTTPRequestHandler * HTTPHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & request)
{
LOG_TRACE(log, "HTTP Request for " << name << ". "
<< "Method: " << request.getMethod()
<< ", Address: " << request.clientAddress().toString()
<< ", User-Agent: " << (request.has("User-Agent") ? request.get("User-Agent") : "none")
<< (request.hasContentLength() ? (", Length: " + std::to_string(request.getContentLength())) : (""))
<< ", Content Type: " << request.getContentType()
<< ", Transfer Encoding: " << request.getTransferEncoding());
for (const auto & [matcher, creator] : handlers_creator)
{
if (matcher(request))
return creator();
}
return new NotFoundHandler(no_handler_description);
}
HTTPHandlerMatcher createRootHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createPingHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createDynamicQueryHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createReplicasStatusHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createPredefinedQueryHandlerMatcher(IServer &, const String &);
HTTPHandlerCreator createRootHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createPingHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createDynamicQueryHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createReplicasStatusHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createPredefinedQueryHandlerCreator(IServer &, const String &);
void HTTPHandlerFactory::updateHTTPHandlersCreator(Poco::Util::AbstractConfiguration & configuration, const String & key)
{
Poco::Util::AbstractConfiguration::Keys http_handlers_item_key;
configuration.keys(key, http_handlers_item_key);
handlers_creator.reserve(http_handlers_item_key.size());
for (const auto & http_handler_type_name : http_handlers_item_key)
{
if (http_handler_type_name.find('.') != String::npos)
throw Exception("HTTPHandler type name with dots are not supported: '" + http_handler_type_name + "'", ErrorCodes::SYNTAX_ERROR);
const auto & handler_key = key + "." + http_handler_type_name;
if (startsWith(http_handler_type_name, "root_handler"))
handlers_creator.push_back({createRootHandlerMatcher(server, handler_key), createRootHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "ping_handler"))
handlers_creator.push_back({createPingHandlerMatcher(server, handler_key), createPingHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "dynamic_query_handler"))
handlers_creator.push_back({createDynamicQueryHandlerMatcher(server, handler_key), createDynamicQueryHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "predefined_query_handler"))
handlers_creator.push_back({createPredefinedQueryHandlerMatcher(server, handler_key), createPredefinedQueryHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "replicas_status_handler"))
handlers_creator.push_back({createReplicasStatusHandlerMatcher(server, handler_key), createReplicasStatusHandlerCreator(server, handler_key)});
else if (http_handler_type_name == "no_handler_description")
no_handler_description = configuration.getString(key + ".no_handler_description");
else
throw Exception("Unknown HTTPHandler type name: " + http_handler_type_name, ErrorCodes::UNKNOWN_HTTP_HANDLER_TYPE);
}
}
}
#pragma once
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Util/AbstractConfiguration.h>
#include <common/logger_useful.h>
#include "IServer.h"
#include "InterserverIOHTTPHandler.h"
namespace DB
{
class InterserverIOHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
public:
InterserverIOHTTPHandlerFactory(IServer & server_, const std::string & name_);
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override;
private:
IServer & server;
Logger * log;
std::string name;
};
using HTTPHandlerCreator = std::function<Poco::Net::HTTPRequestHandler * ()>;
using HTTPHandlerMatcher = std::function<bool(const Poco::Net::HTTPServerRequest &)>;
using HTTPHandlerMatcherAndCreator = std::pair<HTTPHandlerMatcher, HTTPHandlerCreator>;
using HTTPHandlersMatcherAndCreator = std::vector<HTTPHandlerMatcherAndCreator>;
class HTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
public:
HTTPHandlerFactory(IServer & server_, const std::string & name_);
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override;
void updateHTTPHandlersCreator(Poco::Util::AbstractConfiguration & configuration, const String & key = "http_handlers");
private:
IServer & server;
Logger * log;
std::string name;
String no_handler_description;
HTTPHandlersMatcherAndCreator handlers_creator;
};
}
......@@ -328,15 +328,8 @@ void HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne
internal_compression = params.getParsed<bool>("compress", false);
/// Workaround. Poco does not detect 411 Length Required case.
<<<<<<< HEAD:programs/server/HTTPHandler.cpp
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST && !request.getChunkedTransferEncoding() && !request.hasContentLength())
throw Exception("The Transfer-Encoding is not chunked and there is no Content-Length header for POST request", ErrorCodes::HTTP_LENGTH_REQUIRED);
=======
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST
&& !request.getChunkedTransferEncoding()
&& !request.hasContentLength())
throw Exception("There is neither Transfer-Encoding header nor Content-Length header", ErrorCodes::HTTP_LENGTH_REQUIRED);
>>>>>>> ISSUES-5436 fix build failure & fix test failure:dbms/programs/server/HTTPHandler.cpp
{
Context query_context = server.context();
......
#include "HTTPHandlerFactory.h"
#include "NotFoundHandler.h"
#include "HTTPRequestHandler/HTTPRootRequestHandler.h"
#include "HTTPRequestHandler/HTTPPingRequestHandler.h"
#include "HTTPRequestHandler/HTTPReplicasStatusRequestHandler.h"
namespace DB
{
HTTPRequestHandlerFactoryMain::HTTPRequestHandlerFactoryMain(IServer & server_, const std::string & name_)
namespace ErrorCodes
{
extern const int SYNTAX_ERROR;
extern const int UNKNOWN_HTTP_HANDLER_TYPE;
extern const int EMPTY_HTTP_HANDLER_IN_CONFIG;
}
InterserverIOHTTPHandlerFactory::InterserverIOHTTPHandlerFactory(IServer & server_, const std::string & name_)
: server(server_), log(&Logger::get(name_)), name(name_)
{
}
Poco::Net::HTTPRequestHandler * HTTPRequestHandlerFactoryMain::createRequestHandler(
const Poco::Net::HTTPServerRequest & request) // override
Poco::Net::HTTPRequestHandler * InterserverIOHTTPHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & request)
{
LOG_TRACE(log, "HTTP Request for " << name << ". "
<< "Method: "
<< request.getMethod()
<< ", Address: "
<< request.clientAddress().toString()
<< ", User-Agent: "
<< (request.has("User-Agent") ? request.get("User-Agent") : "none")
<< (request.hasContentLength() ? (", Length: " + std::to_string(request.getContentLength())) : (""))
<< ", Content Type: " << request.getContentType()
<< ", Transfer Encoding: " << request.getTransferEncoding());
for (auto & handler_factory : child_handler_factories)
<< "Method: " << request.getMethod()
<< ", Address: " << request.clientAddress().toString()
<< ", User-Agent: " << (request.has("User-Agent") ? request.get("User-Agent") : "none")
<< (request.hasContentLength() ? (", Length: " + std::to_string(request.getContentLength())) : (""))
<< ", Content Type: " << request.getContentType()
<< ", Transfer Encoding: " << request.getTransferEncoding());
const auto & uri = request.getURI();
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD)
{
if (uri == "/")
return new HTTPRootRequestHandler(server);
if (uri == "/ping")
return new HTTPPingRequestHandler(server);
else if (startsWith(uri, "/replicas_status"))
return new HTTPReplicasStatusRequestHandler(server.context());
}
if (uri.find('?') != std::string::npos || request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
{
auto handler = handler_factory->createRequestHandler(request);
if (handler != nullptr)
return handler;
return new InterserverIOHTTPHandler(server);
}
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
{
return new NotFoundHandler;
return new NotFoundHandler(
"Use / or /ping for health checks.\n"
"Or /replicas_status for more sophisticated health checks.\n"
"Send queries from your program with POST method or GET /?query=...\n\n"
" Use clickhouse-client:\n\n"
" For interactive data analysis:\n"
" clickhouse-client\n\n"
" For batch query processing:\n"
" clickhouse-client --query='SELECT 1' > result\n"
" clickhouse-client < query > result"
);
}
return nullptr;
}
HTTPHandlerFactory::HTTPHandlerFactory(IServer & server_, const std::string & name_)
: server(server_), log(&Logger::get(name_)), name(name_)
{
updateHTTPHandlersCreator(server.config());
if (handlers_creator.empty())
throw Exception("The HTTPHandlers does not exist in the config.xml", ErrorCodes::EMPTY_HTTP_HANDLER_IN_CONFIG);
}
Poco::Net::HTTPRequestHandler * HTTPHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & request)
{
LOG_TRACE(log, "HTTP Request for " << name << ". "
<< "Method: " << request.getMethod()
<< ", Address: " << request.clientAddress().toString()
<< ", User-Agent: " << (request.has("User-Agent") ? request.get("User-Agent") : "none")
<< (request.hasContentLength() ? (", Length: " + std::to_string(request.getContentLength())) : (""))
<< ", Content Type: " << request.getContentType()
<< ", Transfer Encoding: " << request.getTransferEncoding());
for (const auto & [matcher, creator] : handlers_creator)
{
if (matcher(request))
return creator();
}
return new NotFoundHandler(no_handler_description);
}
HTTPHandlerMatcher createRootHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createPingHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createDynamicQueryHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createReplicasStatusHandlerMatcher(IServer &, const String &);
HTTPHandlerMatcher createPredefinedQueryHandlerMatcher(IServer &, const String &);
HTTPHandlerCreator createRootHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createPingHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createDynamicQueryHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createReplicasStatusHandlerCreator(IServer &, const String &);
HTTPHandlerCreator createPredefinedQueryHandlerCreator(IServer &, const String &);
void HTTPHandlerFactory::updateHTTPHandlersCreator(Poco::Util::AbstractConfiguration & configuration, const String & key)
{
Poco::Util::AbstractConfiguration::Keys http_handlers_item_key;
configuration.keys(key, http_handlers_item_key);
handlers_creator.reserve(http_handlers_item_key.size());
for (const auto & http_handler_type_name : http_handlers_item_key)
{
if (http_handler_type_name.find('.') != String::npos)
throw Exception("HTTPHandler type name with dots are not supported: '" + http_handler_type_name + "'", ErrorCodes::SYNTAX_ERROR);
const auto & handler_key = key + "." + http_handler_type_name;
if (startsWith(http_handler_type_name, "root_handler"))
handlers_creator.push_back({createRootHandlerMatcher(server, handler_key), createRootHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "ping_handler"))
handlers_creator.push_back({createPingHandlerMatcher(server, handler_key), createPingHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "dynamic_query_handler"))
handlers_creator.push_back({createDynamicQueryHandlerMatcher(server, handler_key), createDynamicQueryHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "predefined_query_handler"))
handlers_creator.push_back({createPredefinedQueryHandlerMatcher(server, handler_key), createPredefinedQueryHandlerCreator(server, handler_key)});
else if (startsWith(http_handler_type_name, "replicas_status_handler"))
handlers_creator.push_back({createReplicasStatusHandlerMatcher(server, handler_key), createReplicasStatusHandlerCreator(server, handler_key)});
else if (http_handler_type_name == "no_handler_description")
no_handler_description = configuration.getString(key + ".no_handler_description");
else
throw Exception("Unknown HTTPHandler type name: " + http_handler_type_name, ErrorCodes::UNKNOWN_HTTP_HANDLER_TYPE);
}
}
}
#pragma once
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Util/AbstractConfiguration.h>
#include <common/logger_useful.h>
#include "IServer.h"
#include "HTTPHandler.h"
#include "InterserverIOHTTPHandler.h"
#include "NotFoundHandler.h"
#include "PingRequestHandler.h"
#include "PrometheusRequestHandler.h"
#include "ReplicasStatusHandler.h"
#include "RootRequestHandler.h"
namespace DB
{
/// Handle request using child handlers
class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory
class InterserverIOHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
private:
using TThis = HTTPRequestHandlerFactoryMain;
IServer & server;
Logger * log;
std::string name;
std::vector<std::unique_ptr<Poco::Net::HTTPRequestHandlerFactory>> child_handler_factories;
public:
HTTPRequestHandlerFactoryMain(IServer & server_, const std::string & name_);
InterserverIOHTTPHandlerFactory(IServer & server_, const std::string & name_);
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override;
template <typename T, typename... TArgs>
TThis * addHandler(TArgs &&... args)
{
child_handler_factories.emplace_back(std::make_unique<T>(server, std::forward<TArgs>(args)...));
return this;
}
};
/// Handle POST or GET with params
template <typename HandleType>
class HTTPQueryRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
private:
IServer & server;
public:
HTTPQueryRequestHandlerFactory(IServer & server_) : server(server_) {}
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override
{
if (request.getURI().find('?') != std::string::npos || request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
return new HandleType(server);
return nullptr;
}
Logger * log;
std::string name;
};
using HTTPHandlerCreator = std::function<Poco::Net::HTTPRequestHandler * ()>;
using HTTPHandlerMatcher = std::function<bool(const Poco::Net::HTTPServerRequest &)>;
using HTTPHandlerMatcherAndCreator = std::pair<HTTPHandlerMatcher, HTTPHandlerCreator>;
using HTTPHandlersMatcherAndCreator = std::vector<HTTPHandlerMatcherAndCreator>;
/// Handle GET or HEAD endpoint on specified path
template <typename TGetEndpoint>
class HTTPGetRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
class HTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
private:
IServer & server;
public:
HTTPGetRequestHandlerFactory(IServer & server_) : server(server_) {}
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override
{
auto & method = request.getMethod();
if (!(method == Poco::Net::HTTPRequest::HTTP_GET || method == Poco::Net::HTTPRequest::HTTP_HEAD))
return nullptr;
auto & uri = request.getURI();
bool uri_match = TGetEndpoint::strict_path ? uri == TGetEndpoint::path : startsWith(uri, TGetEndpoint::path);
if (uri_match)
return new typename TGetEndpoint::HandleType(server);
return nullptr;
}
};
HTTPHandlerFactory(IServer & server_, const std::string & name_);
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override;
struct RootEndpoint
{
static constexpr auto path = "/";
static constexpr auto strict_path = true;
using HandleType = RootRequestHandler;
};
void updateHTTPHandlersCreator(Poco::Util::AbstractConfiguration & configuration, const String & key = "http_handlers");
struct PingEndpoint
{
static constexpr auto path = "/ping";
static constexpr auto strict_path = true;
using HandleType = PingRequestHandler;
};
private:
IServer & server;
Logger * log;
std::string name;
struct ReplicasStatusEndpoint
{
static constexpr auto path = "/replicas_status";
static constexpr auto strict_path = false;
using HandleType = ReplicasStatusHandler;
String no_handler_description;
HTTPHandlersMatcherAndCreator handlers_creator;
};
using HTTPRootRequestHandlerFactory = HTTPGetRequestHandlerFactory<RootEndpoint>;
using HTTPPingRequestHandlerFactory = HTTPGetRequestHandlerFactory<PingEndpoint>;
using HTTPReplicasStatusRequestHandlerFactory = HTTPGetRequestHandlerFactory<ReplicasStatusEndpoint>;
template <typename HandleType>
HTTPRequestHandlerFactoryMain * createDefaultHandlerFatory(IServer & server, const std::string & name)
{
auto handlerFactory = new HTTPRequestHandlerFactoryMain(server, name);
handlerFactory->addHandler<HTTPRootRequestHandlerFactory>()
->addHandler<HTTPPingRequestHandlerFactory>()
->addHandler<HTTPReplicasStatusRequestHandlerFactory>()
->addHandler<HTTPQueryRequestHandlerFactory<HandleType>>();
return handlerFactory;
}
}
......@@ -9,11 +9,6 @@
namespace DB
{
namespace ErrorCodes
{
extern const int UNKNOWN_HTTP_PARAM;
}
class ExtractorContextChange
{
public:
......
......@@ -156,19 +156,16 @@ HTTPResponseBufferPtr HTTPQueryRequestHandler<QueryParamExtractor>::createRespon
/// Both gzip and deflate are supported. If the client supports both, gzip is preferred.
/// NOTE parsing of the list of methods is slightly incorrect.
if (std::string::npos != http_response_compression_methods.find("gzip"))
return std::make_shared<WriteBufferFromHTTPServerResponse>(
request, response, keep_alive, true, CompressionMethod::Gzip, DBMS_DEFAULT_BUFFER_SIZE);
return std::make_shared<WriteBufferFromHTTPServerResponse>(request, response, keep_alive, true, CompressionMethod::Gzip);
else if (std::string::npos != http_response_compression_methods.find("deflate"))
return std::make_shared<WriteBufferFromHTTPServerResponse>(
request, response, keep_alive, true, CompressionMethod::Zlib, DBMS_DEFAULT_BUFFER_SIZE);
return std::make_shared<WriteBufferFromHTTPServerResponse>(request, response, keep_alive, true, CompressionMethod::Zlib);
#if USE_BROTLI
else if (http_response_compression_methods == "br")
return std::make_shared<WriteBufferFromHTTPServerResponse>(
request, response, keep_alive, true, CompressionMethod::Brotli, DBMS_DEFAULT_BUFFER_SIZE);
return std::make_shared<WriteBufferFromHTTPServerResponse>(request, response, keep_alive, true, CompressionMethod::Brotli);
#endif
}
return std::make_shared<WriteBufferFromHTTPServerResponse>(request, response, keep_alive, false, CompressionMethod{}, DBMS_DEFAULT_BUFFER_SIZE);
return std::make_shared<WriteBufferFromHTTPServerResponse>(request, response, keep_alive, false, CompressionMethod{});
}
......
......@@ -107,57 +107,36 @@ void WriteBufferFromHTTPServerResponse::nextImpl()
{
if (compress)
{
if (compression_method == CompressionMethod::Gzip)
{
#if defined(POCO_CLICKHOUSE_PATCH)
*response_header_ostr << "Content-Encoding: gzip\r\n";
#else
response.set("Content-Encoding", "gzip");
response_body_ostr = &(response.send());
#endif
out_raw = std::make_unique<WriteBufferFromOStream>(*response_body_ostr);
deflating_buf.emplace(std::move(out_raw), compression_method, compression_level, working_buffer.size(), working_buffer.begin());
out = &*deflating_buf;
}
else if (compression_method == CompressionMethod::Zlib)
{
#if defined(POCO_CLICKHOUSE_PATCH)
*response_header_ostr << "Content-Encoding: deflate\r\n";
#else
response.set("Content-Encoding", "deflate");
response_body_ostr = &(response.send());
#endif
out_raw = std::make_unique<WriteBufferFromOStream>(*response_body_ostr);
deflating_buf.emplace(std::move(out_raw), compression_method, compression_level, working_buffer.size(), working_buffer.begin());
out = &*deflating_buf;
}
#if USE_BROTLI
else if (compression_method == CompressionMethod::Brotli)
{
auto content_encoding_name = toContentEncodingName(compression_method);
#if defined(POCO_CLICKHOUSE_PATCH)
*response_header_ostr << "Content-Encoding: br\r\n";
*response_header_ostr << "Content-Encoding: " << content_encoding_name << "\r\n";
#else
response.set("Content-Encoding", content_encoding_name);
#endif
else
throw Exception("Logical error: unknown compression method passed to WriteBufferFromHTTPServerResponse",
ErrorCodes::LOGICAL_ERROR);
/// Use memory allocated for the outer buffer in the buffer pointed to by out. This avoids extra allocation and copy.
}
else
{
#if !defined(POCO_CLICKHOUSE_PATCH)
response_body_ostr = &(response.send());
response_body_ostr = &(response.send());
#endif
out_raw = std::make_unique<WriteBufferFromOStream>(*response_body_ostr, working_buffer.size(), working_buffer.begin());
out = &*out_raw;
}
/// We reuse our buffer in "out" to avoid extra allocations and copies.
if (compress)
out = wrapWriteBufferWithCompressionMethod(
std::make_unique<WriteBufferFromOStream>(*response_body_ostr),
compress ? compression_method : CompressionMethod::None,
compression_level,
working_buffer.size(),
working_buffer.begin());
else
out = std::make_unique<WriteBufferFromOStream>(
*response_body_ostr,
working_buffer.size(),
working_buffer.begin());
}
finishSendHeaders();
}
if (out)
......@@ -174,9 +153,8 @@ WriteBufferFromHTTPServerResponse::WriteBufferFromHTTPServerResponse(
Poco::Net::HTTPServerResponse & response_,
unsigned keep_alive_timeout_,
bool compress_,
CompressionMethod compression_method_,
size_t size)
: BufferWithOwnMemory<WriteBuffer>(size)
CompressionMethod compression_method_)
: BufferWithOwnMemory<WriteBuffer>(DBMS_DEFAULT_BUFFER_SIZE)
, request(request_)
, response(response_)
, keep_alive_timeout(keep_alive_timeout_)
......
......@@ -95,8 +95,7 @@ public:
Poco::Net::HTTPServerResponse & response_,
unsigned keep_alive_timeout_,
bool compress_ = false, /// If true - set Content-Encoding header and compress the result.
CompressionMethod compression_method_ = CompressionMethod::Gzip,
size_t size = DBMS_DEFAULT_BUFFER_SIZE);
CompressionMethod compression_method_ = CompressionMethod::None);
/// Writes progess in repeating HTTP headers.
void onProgress(const Progress & progress);
......
......@@ -106,6 +106,7 @@ class Volume;
using VolumePtr = std::shared_ptr<Volume>;
struct NamedSession;
#if USE_EMBEDDED_COMPILER
class CompiledExpressionCache;
#endif
......
......@@ -55,7 +55,7 @@ void ReplaceQueryParameterVisitor::visitQueryParameter(ASTPtr & ast)
IColumn & temp_column = *temp_column_ptr;
ReadBufferFromString read_buffer{value};
FormatSettings format_settings;
data_type->deserializeAsWholeText(temp_column, read_buffer, format_settings);
data_type->deserializeAsTextEscaped(temp_column, read_buffer, format_settings);
if (!read_buffer.eof())
throw Exception("Value " + value + " cannot be parsed as " + type_name + " for query parameter '" + ast_param.name + "'"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册