mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
minor fixes
This commit is contained in:
parent
d56002b81f
commit
e72a484beb
@ -755,15 +755,15 @@ std::string DynamicQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request
|
|||||||
return full_query;
|
return full_query;
|
||||||
}
|
}
|
||||||
|
|
||||||
PredefineQueryHandler::PredefineQueryHandler(
|
PredefinedQueryHandler::PredefinedQueryHandler(
|
||||||
IServer & server, const NameSet & receive_params_, const std::string & predefine_query_
|
IServer & server, const NameSet & receive_params_, const std::string & predefined_query_
|
||||||
, const std::optional<String> & url_regex_, const std::unordered_map<String, String> & header_name_with_regex_)
|
, const std::optional<String> & url_regex_, const std::unordered_map<String, String> & header_name_with_regex_)
|
||||||
: HTTPHandler(server, "PredefineQueryHandler"), receive_params(receive_params_), predefine_query(predefine_query_)
|
: HTTPHandler(server, "PredefinedQueryHandler"), receive_params(receive_params_), predefined_query(predefined_query_)
|
||||||
, url_regex(url_regex_), header_name_with_capture_regex(header_name_with_regex_)
|
, url_regex(url_regex_), header_name_with_capture_regex(header_name_with_regex_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PredefineQueryHandler::customizeQueryParam(Context & context, const std::string & key, const std::string & value)
|
bool PredefinedQueryHandler::customizeQueryParam(Context & context, const std::string & key, const std::string & value)
|
||||||
{
|
{
|
||||||
if (receive_params.count(key))
|
if (receive_params.count(key))
|
||||||
{
|
{
|
||||||
@ -774,7 +774,7 @@ bool PredefineQueryHandler::customizeQueryParam(Context & context, const std::st
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & request, DB::Context & context)
|
void PredefinedQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & request, DB::Context & context)
|
||||||
{
|
{
|
||||||
/// If in the configuration file, the handler's header is regex and contains named capture group
|
/// If in the configuration file, the handler's header is regex and contains named capture group
|
||||||
/// We will extract regex named capture groups as query parameters
|
/// We will extract regex named capture groups as query parameters
|
||||||
@ -784,7 +784,7 @@ void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & requ
|
|||||||
auto compiled_regex = std::make_shared<re2_st::RE2>(regex);
|
auto compiled_regex = std::make_shared<re2_st::RE2>(regex);
|
||||||
|
|
||||||
if (!compiled_regex->ok())
|
if (!compiled_regex->ok())
|
||||||
throw Exception("cannot compile re2: " + regex + " for routing_rule, error: " + compiled_regex->error() +
|
throw Exception("cannot compile re2: " + regex + " for http handling rule, error: " + compiled_regex->error() +
|
||||||
". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
||||||
|
|
||||||
int num_captures = compiled_regex->NumberOfCapturingGroups() + 1;
|
int num_captures = compiled_regex->NumberOfCapturingGroups() + 1;
|
||||||
@ -816,7 +816,7 @@ void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & requ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PredefineQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request, HTMLForm & params, Context & context)
|
std::string PredefinedQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request, HTMLForm & params, Context & context)
|
||||||
{
|
{
|
||||||
if (unlikely(startsWith(request.getContentType(), "multipart/form-data")))
|
if (unlikely(startsWith(request.getContentType(), "multipart/form-data")))
|
||||||
{
|
{
|
||||||
@ -825,13 +825,13 @@ std::string PredefineQueryHandler::getQuery(Poco::Net::HTTPServerRequest & reque
|
|||||||
params.load(request, request.stream(), handler);
|
params.load(request, request.stream(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
return predefine_query;
|
return predefined_query;
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix)
|
Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix)
|
||||||
{
|
{
|
||||||
std::string query_param_name = server.config().getString(config_prefix + ".handler.query_param_name", "query");
|
std::string query_param_name = server.config().getString(config_prefix + ".handler.query_param_name", "query");
|
||||||
return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory<DynamicQueryHandler>(server, std::move(query_param_name)), server.config(), config_prefix);
|
return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory<DynamicQueryHandler>(server, std::move(query_param_name)), server.config(), config_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool capturingNamedQueryParam(NameSet receive_params, const std::string & expression)
|
static inline bool capturingNamedQueryParam(NameSet receive_params, const std::string & expression)
|
||||||
@ -839,7 +839,7 @@ static inline bool capturingNamedQueryParam(NameSet receive_params, const std::s
|
|||||||
auto compiled_regex = std::make_shared<re2_st::RE2>(expression);
|
auto compiled_regex = std::make_shared<re2_st::RE2>(expression);
|
||||||
|
|
||||||
if (!compiled_regex->ok())
|
if (!compiled_regex->ok())
|
||||||
throw Exception("Cannot compile re2: " + expression + " for routing_rule, error: " +
|
throw Exception("Cannot compile re2: " + expression + " for http handling rule, error: " +
|
||||||
compiled_regex->error() + ". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
compiled_regex->error() + ". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
||||||
|
|
||||||
const auto & capturing_names = compiled_regex->NamedCapturingGroups();
|
const auto & capturing_names = compiled_regex->NamedCapturingGroups();
|
||||||
@ -850,15 +850,15 @@ static inline bool capturingNamedQueryParam(NameSet receive_params, const std::s
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & server, const std::string & config_prefix)
|
Poco::Net::HTTPRequestHandlerFactory * createPredefinedHandlerFactory(IServer & server, const std::string & config_prefix)
|
||||||
{
|
{
|
||||||
Poco::Util::AbstractConfiguration & configuration = server.config();
|
Poco::Util::AbstractConfiguration & configuration = server.config();
|
||||||
|
|
||||||
if (!configuration.has(config_prefix + ".handler.query"))
|
if (!configuration.has(config_prefix + ".handler.query"))
|
||||||
throw Exception("There is no path '" + config_prefix + ".handler.query" + "' in configuration file.", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
throw Exception("There is no path '" + config_prefix + ".handler.query" + "' in configuration file.", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
||||||
|
|
||||||
std::string predefine_query = configuration.getString(config_prefix + ".handler.query");
|
std::string predefined_query = configuration.getString(config_prefix + ".handler.query");
|
||||||
NameSet analyze_receive_params = analyzeReceiveQueryParams(predefine_query);
|
NameSet analyze_receive_params = analyzeReceiveQueryParams(predefined_query);
|
||||||
|
|
||||||
std::unordered_map<String, String> headers_name_with_regex;
|
std::unordered_map<String, String> headers_name_with_regex;
|
||||||
Poco::Util::AbstractConfiguration::Keys headers_name;
|
Poco::Util::AbstractConfiguration::Keys headers_name;
|
||||||
@ -884,13 +884,13 @@ Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & s
|
|||||||
url_expression = url_expression.substr(6);
|
url_expression = url_expression.substr(6);
|
||||||
|
|
||||||
if (capturingNamedQueryParam(analyze_receive_params, url_expression))
|
if (capturingNamedQueryParam(analyze_receive_params, url_expression))
|
||||||
return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory<PredefineQueryHandler>(
|
return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory<PredefinedQueryHandler>(
|
||||||
server, std::move(analyze_receive_params), std::move(predefine_query), std::optional<String>(url_expression),
|
server, std::move(analyze_receive_params), std::move(predefined_query), std::optional<String>(url_expression),
|
||||||
std::move(headers_name_with_regex)), configuration, config_prefix);
|
std::move(headers_name_with_regex)), configuration, config_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory<PredefineQueryHandler>(
|
return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory<PredefinedQueryHandler>(
|
||||||
server, std::move(analyze_receive_params), std::move(predefine_query), std::optional<String>{} ,std::move(headers_name_with_regex)),
|
server, std::move(analyze_receive_params), std::move(predefined_query), std::optional<String>{} ,std::move(headers_name_with_regex)),
|
||||||
configuration, config_prefix);
|
configuration, config_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override;
|
void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override;
|
||||||
|
|
||||||
/// This method is called right before the query execution.
|
/// This method is called right before the query execution.
|
||||||
virtual void customizeContext(Poco::Net::HTTPServerRequest & request, Context & /* context */) {}
|
virtual void customizeContext(Poco::Net::HTTPServerRequest & /*request*/, Context & /* context */) {}
|
||||||
|
|
||||||
virtual bool customizeQueryParam(Context & context, const std::string & key, const std::string & value) = 0;
|
virtual bool customizeQueryParam(Context & context, const std::string & key, const std::string & value) = 0;
|
||||||
|
|
||||||
@ -96,16 +96,16 @@ public:
|
|||||||
bool customizeQueryParam(Context &context, const std::string &key, const std::string &value) override;
|
bool customizeQueryParam(Context &context, const std::string &key, const std::string &value) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PredefineQueryHandler : public HTTPHandler
|
class PredefinedQueryHandler : public HTTPHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
NameSet receive_params;
|
NameSet receive_params;
|
||||||
std::string predefine_query;
|
std::string predefined_query;
|
||||||
std::optional<String> url_regex;
|
std::optional<String> url_regex;
|
||||||
std::unordered_map<String, String> header_name_with_capture_regex;
|
std::unordered_map<String, String> header_name_with_capture_regex;
|
||||||
public:
|
public:
|
||||||
explicit PredefineQueryHandler(
|
explicit PredefinedQueryHandler(
|
||||||
IServer & server, const NameSet & receive_params_, const std::string & predefine_query_
|
IServer & server, const NameSet & receive_params_, const std::string & predefined_query_
|
||||||
, const std::optional<String> & url_regex_, const std::unordered_map<String, String> & header_name_with_regex_);
|
, const std::optional<String> & url_regex_, const std::unordered_map<String, String> & header_name_with_regex_);
|
||||||
|
|
||||||
virtual void customizeContext(Poco::Net::HTTPServerRequest & request, Context & context) override;
|
virtual void customizeContext(Poco::Net::HTTPServerRequest & request, Context & context) override;
|
||||||
|
@ -26,6 +26,7 @@ namespace ErrorCodes
|
|||||||
{
|
{
|
||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
extern const int UNKNOWN_ELEMENT_IN_CONFIG;
|
extern const int UNKNOWN_ELEMENT_IN_CONFIG;
|
||||||
|
extern const int INVALID_CONFIG_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPRequestHandlerFactoryMain::HTTPRequestHandlerFactoryMain(const std::string & name_)
|
HTTPRequestHandlerFactoryMain::HTTPRequestHandlerFactoryMain(const std::string & name_)
|
||||||
@ -63,7 +64,10 @@ Poco::Net::HTTPRequestHandler * HTTPRequestHandlerFactoryMain::createRequestHand
|
|||||||
HTTPRequestHandlerFactoryMain::~HTTPRequestHandlerFactoryMain()
|
HTTPRequestHandlerFactoryMain::~HTTPRequestHandlerFactoryMain()
|
||||||
{
|
{
|
||||||
while (!child_factories.empty())
|
while (!child_factories.empty())
|
||||||
delete child_factories.back(), child_factories.pop_back();
|
{
|
||||||
|
delete child_factories.back();
|
||||||
|
child_factories.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPRequestHandlerFactoryMain::TThis * HTTPRequestHandlerFactoryMain::addHandler(Poco::Net::HTTPRequestHandlerFactory * child_factory)
|
HTTPRequestHandlerFactoryMain::TThis * HTTPRequestHandlerFactoryMain::addHandler(Poco::Net::HTTPRequestHandlerFactory * child_factory)
|
||||||
@ -83,8 +87,8 @@ static inline auto createHandlersFactoryFromConfig(IServer & server, const std::
|
|||||||
|
|
||||||
for (const auto & key : keys)
|
for (const auto & key : keys)
|
||||||
{
|
{
|
||||||
if (!startsWith(key, "routing_rule"))
|
if (!startsWith(key, "rule"))
|
||||||
throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'routing_rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
|
throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
|
||||||
|
|
||||||
const auto & handler_type = server.config().getString(prefix + "." + key + ".handler.type", "");
|
const auto & handler_type = server.config().getString(prefix + "." + key + ".handler.type", "");
|
||||||
|
|
||||||
@ -92,10 +96,14 @@ static inline auto createHandlersFactoryFromConfig(IServer & server, const std::
|
|||||||
main_handler_factory->addHandler(createStaticHandlerFactory(server, prefix + "." + key));
|
main_handler_factory->addHandler(createStaticHandlerFactory(server, prefix + "." + key));
|
||||||
else if (handler_type == "dynamic_query_handler")
|
else if (handler_type == "dynamic_query_handler")
|
||||||
main_handler_factory->addHandler(createDynamicHandlerFactory(server, prefix + "." + key));
|
main_handler_factory->addHandler(createDynamicHandlerFactory(server, prefix + "." + key));
|
||||||
else if (handler_type == "predefine_query_handler")
|
else if (handler_type == "predefined_query_handler")
|
||||||
main_handler_factory->addHandler(createPredefineHandlerFactory(server, prefix + "." + key));
|
main_handler_factory->addHandler(createPredefinedHandlerFactory(server, prefix + "." + key));
|
||||||
|
else if (handler_type.empty())
|
||||||
|
throw Exception("Handler type in config is not specified here: " +
|
||||||
|
prefix + "." + key + ".handler.type", ErrorCodes::INVALID_CONFIG_PARAMETER);
|
||||||
else
|
else
|
||||||
throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'routing_rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
|
throw Exception("Unknown handler type '" + handler_type +"' in config here: " +
|
||||||
|
prefix + "." + key + ".handler.type",ErrorCodes::INVALID_CONFIG_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
return main_handler_factory;
|
return main_handler_factory;
|
||||||
@ -112,21 +120,21 @@ static const auto root_response_expression = "config://http_server_default_respo
|
|||||||
|
|
||||||
static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IServer & server, const std::string & name, AsynchronousMetrics & async_metrics)
|
static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IServer & server, const std::string & name, AsynchronousMetrics & async_metrics)
|
||||||
{
|
{
|
||||||
if (server.config().has("routing_rules"))
|
if (server.config().has("http_handlers"))
|
||||||
return createHandlersFactoryFromConfig(server, name, "routing_rules");
|
return createHandlersFactoryFromConfig(server, name, "http_handlers");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto factory = (new HTTPRequestHandlerFactoryMain(name))
|
auto factory = (new HTTPRequestHandlerFactoryMain(name))
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<StaticRequestHandler>(server, root_response_expression))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<StaticRequestHandler>(server, root_response_expression))
|
||||||
->attachStrictPath("/")->allowGetAndHeadRequest())
|
->attachStrictPath("/")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<StaticRequestHandler>(server, ping_response_expression))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<StaticRequestHandler>(server, ping_response_expression))
|
||||||
->attachStrictPath("/ping")->allowGetAndHeadRequest())
|
->attachStrictPath("/ping")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<ReplicasStatusHandler>(server))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<ReplicasStatusHandler>(server))
|
||||||
->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest())
|
->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<DynamicQueryHandler>(server, "query"))->allowPostAndGetParamsRequest());
|
->addHandler((new HandlingRuleHTTPHandlerFactory<DynamicQueryHandler>(server, "query"))->allowPostAndGetParamsRequest());
|
||||||
|
|
||||||
if (server.config().has("prometheus") && server.config().getInt("prometheus.port", 0) == 0)
|
if (server.config().has("prometheus") && server.config().getInt("prometheus.port", 0) == 0)
|
||||||
factory->addHandler((new RoutingRuleHTTPHandlerFactory<PrometheusRequestHandler>(
|
factory->addHandler((new HandlingRuleHTTPHandlerFactory<PrometheusRequestHandler>(
|
||||||
server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics)))
|
server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics)))
|
||||||
->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest());
|
->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest());
|
||||||
|
|
||||||
@ -137,13 +145,13 @@ static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IS
|
|||||||
static inline Poco::Net::HTTPRequestHandlerFactory * createInterserverHTTPHandlerFactory(IServer & server, const std::string & name)
|
static inline Poco::Net::HTTPRequestHandlerFactory * createInterserverHTTPHandlerFactory(IServer & server, const std::string & name)
|
||||||
{
|
{
|
||||||
return (new HTTPRequestHandlerFactoryMain(name))
|
return (new HTTPRequestHandlerFactoryMain(name))
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<StaticRequestHandler>(server, root_response_expression))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<StaticRequestHandler>(server, root_response_expression))
|
||||||
->attachStrictPath("/")->allowGetAndHeadRequest())
|
->attachStrictPath("/")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<StaticRequestHandler>(server, ping_response_expression))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<StaticRequestHandler>(server, ping_response_expression))
|
||||||
->attachStrictPath("/ping")->allowGetAndHeadRequest())
|
->attachStrictPath("/ping")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<ReplicasStatusHandler>(server))
|
->addHandler((new HandlingRuleHTTPHandlerFactory<ReplicasStatusHandler>(server))
|
||||||
->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest())
|
->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest())
|
||||||
->addHandler((new RoutingRuleHTTPHandlerFactory<InterserverIOHTTPHandler>(server))->allowPostAndGetParamsRequest());
|
->addHandler((new HandlingRuleHTTPHandlerFactory<InterserverIOHTTPHandler>(server))->allowPostAndGetParamsRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name)
|
Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name)
|
||||||
@ -153,11 +161,11 @@ Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, As
|
|||||||
else if (name == "InterserverIOHTTPHandler-factory" || name == "InterserverIOHTTPSHandler-factory")
|
else if (name == "InterserverIOHTTPHandler-factory" || name == "InterserverIOHTTPSHandler-factory")
|
||||||
return createInterserverHTTPHandlerFactory(server, name);
|
return createInterserverHTTPHandlerFactory(server, name);
|
||||||
else if (name == "PrometheusHandler-factory")
|
else if (name == "PrometheusHandler-factory")
|
||||||
return (new HTTPRequestHandlerFactoryMain(name))->addHandler((new RoutingRuleHTTPHandlerFactory<PrometheusRequestHandler>(
|
return (new HTTPRequestHandlerFactoryMain(name))->addHandler((new HandlingRuleHTTPHandlerFactory<PrometheusRequestHandler>(
|
||||||
server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics)))
|
server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics)))
|
||||||
->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest());
|
->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest());
|
||||||
|
|
||||||
throw Exception("LOGICAL ERROR: Unknown HTTP handler factory name.", ErrorCodes::LOGICAL_ERROR);
|
throw Exception("LOGICAL ERROR: Unknown HTTP handler factory name.", ErrorCodes::LOGICAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace DB
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// Handle request using child handlers
|
/// Handle request using child handlers
|
||||||
class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory
|
class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory, boost::noncopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using TThis = HTTPRequestHandlerFactoryMain;
|
using TThis = HTTPRequestHandlerFactoryMain;
|
||||||
@ -34,14 +34,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename TEndpoint>
|
template <typename TEndpoint>
|
||||||
class RoutingRuleHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
|
class HandlingRuleHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using TThis = RoutingRuleHTTPHandlerFactory<TEndpoint>;
|
using TThis = HandlingRuleHTTPHandlerFactory<TEndpoint>;
|
||||||
using Filter = std::function<bool(const Poco::Net::HTTPServerRequest &)>;
|
using Filter = std::function<bool(const Poco::Net::HTTPServerRequest &)>;
|
||||||
|
|
||||||
template <typename... TArgs>
|
template <typename... TArgs>
|
||||||
RoutingRuleHTTPHandlerFactory(TArgs &&... args)
|
HandlingRuleHTTPHandlerFactory(TArgs &&... args)
|
||||||
{
|
{
|
||||||
creator = [args = std::tuple<TArgs...>(std::forward<TArgs>(args) ...)]()
|
creator = [args = std::tuple<TArgs...>(std::forward<TArgs>(args) ...)]()
|
||||||
{
|
{
|
||||||
@ -107,7 +107,7 @@ Poco::Net::HTTPRequestHandlerFactory * createStaticHandlerFactory(IServer & serv
|
|||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix);
|
Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix);
|
||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & server, const std::string & config_prefix);
|
Poco::Net::HTTPRequestHandlerFactory * createPredefinedHandlerFactory(IServer & server, const std::string & config_prefix);
|
||||||
|
|
||||||
Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name);
|
Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ static inline bool checkRegexExpression(const StringRef & match_str, const Strin
|
|||||||
auto compiled_regex = std::make_shared<re2_st::RE2>(regex);
|
auto compiled_regex = std::make_shared<re2_st::RE2>(regex);
|
||||||
|
|
||||||
if (!compiled_regex->ok())
|
if (!compiled_regex->ok())
|
||||||
throw Exception("cannot compile re2: " + expression.toString() + " for routing_rule, error: " + compiled_regex->error() +
|
throw Exception("cannot compile re2: " + expression.toString() + " for http handling rule, error: " + compiled_regex->error() +
|
||||||
". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP);
|
||||||
|
|
||||||
int num_captures = compiled_regex->NumberOfCapturingGroups() + 1;
|
int num_captures = compiled_regex->NumberOfCapturingGroups() + 1;
|
||||||
@ -99,7 +99,7 @@ static inline auto headersFilter(Poco::Util::AbstractConfiguration & config, con
|
|||||||
|
|
||||||
template <typename TEndpoint>
|
template <typename TEndpoint>
|
||||||
static inline Poco::Net::HTTPRequestHandlerFactory * addFiltersFromConfig(
|
static inline Poco::Net::HTTPRequestHandlerFactory * addFiltersFromConfig(
|
||||||
RoutingRuleHTTPHandlerFactory <TEndpoint> * factory, Poco::Util::AbstractConfiguration & config, const std::string & prefix)
|
HandlingRuleHTTPHandlerFactory <TEndpoint> * factory, Poco::Util::AbstractConfiguration & config, const std::string & prefix)
|
||||||
{
|
{
|
||||||
Poco::Util::AbstractConfiguration::Keys filters_type;
|
Poco::Util::AbstractConfiguration::Keys filters_type;
|
||||||
config.keys(prefix, filters_type);
|
config.keys(prefix, filters_type);
|
||||||
|
@ -140,7 +140,7 @@ void StaticRequestHandler::writeResponse(WriteBuffer & out)
|
|||||||
else if (startsWith(response_expression, config_prefix))
|
else if (startsWith(response_expression, config_prefix))
|
||||||
{
|
{
|
||||||
if (response_expression.size() <= config_prefix.size())
|
if (response_expression.size() <= config_prefix.size())
|
||||||
throw Exception( "Static routing rule handler must contain a complete configuration path, for example: config://config_key",
|
throw Exception( "Static handling rule handler must contain a complete configuration path, for example: config://config_key",
|
||||||
ErrorCodes::INVALID_CONFIG_PARAMETER);
|
ErrorCodes::INVALID_CONFIG_PARAMETER);
|
||||||
|
|
||||||
const auto & config_path = response_expression.substr(config_prefix.size(), response_expression.size() - config_prefix.size());
|
const auto & config_path = response_expression.substr(config_prefix.size(), response_expression.size() - config_prefix.size());
|
||||||
@ -161,7 +161,7 @@ Poco::Net::HTTPRequestHandlerFactory * createStaticHandlerFactory(IServer & serv
|
|||||||
std::string response_content = server.config().getRawString(config_prefix + ".handler.response_content", "Ok.\n");
|
std::string response_content = server.config().getRawString(config_prefix + ".handler.response_content", "Ok.\n");
|
||||||
std::string response_content_type = server.config().getString(config_prefix + ".handler.content_type", "text/plain; charset=UTF-8");
|
std::string response_content_type = server.config().getString(config_prefix + ".handler.content_type", "text/plain; charset=UTF-8");
|
||||||
|
|
||||||
return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory<StaticRequestHandler>(
|
return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory<StaticRequestHandler>(
|
||||||
server, std::move(response_content), std::move(status), std::move(response_content_type)), server.config(), config_prefix);
|
server, std::move(response_content), std::move(status), std::move(response_content_type)), server.config(), config_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,21 +525,21 @@
|
|||||||
</query_masking_rules>
|
</query_masking_rules>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Uncomment to use custom http routing.
|
<!-- Uncomment to use custom http handlers.
|
||||||
routing_rule are checked from top to bottom, first match runs the handler
|
rules are checked from top to bottom, first match runs the handler
|
||||||
url - to match request URL, you can use 'regex:' prefix to use regex match(optional)
|
url - to match request URL, you can use 'regex:' prefix to use regex match(optional)
|
||||||
methods - to match request method, you can use commas to separate multiple method matches(optional)
|
methods - to match request method, you can use commas to separate multiple method matches(optional)
|
||||||
headers - to match request headers, match each child element(child element name is header name), you can use 'regex:' prefix to use regex match(optional)
|
headers - to match request headers, match each child element(child element name is header name), you can use 'regex:' prefix to use regex match(optional)
|
||||||
handler is request handler
|
handler is request handler
|
||||||
type - supported types: static, dynamic_query_handler, predefine_query_handler
|
type - supported types: static, dynamic_query_handler, predefined_query_handler
|
||||||
query - use with predefine_query_handler type, executes query when the handler is called
|
query - use with predefined_query_handler type, executes query when the handler is called
|
||||||
query_param_name - use with dynamic_query_handler type, extracts and executes the value corresponding to the <query_param_name> value in HTTP request params
|
query_param_name - use with dynamic_query_handler type, extracts and executes the value corresponding to the <query_param_name> value in HTTP request params
|
||||||
status - use with static type, response status code
|
status - use with static type, response status code
|
||||||
content_type - use with static type, response content-type
|
content_type - use with static type, response content-type
|
||||||
response_content - use with static type, Response content sent to client, when using the prefix 'file://' or 'config://', find the content from the file or configuration send to client.
|
response_content - use with static type, Response content sent to client, when using the prefix 'file://' or 'config://', find the content from the file or configuration send to client.
|
||||||
|
|
||||||
<routing_rules>
|
<http_handlers>
|
||||||
<routing_rule>
|
<rule>
|
||||||
<url>/</url>
|
<url>/</url>
|
||||||
<methods>POST,GET</methods>
|
<methods>POST,GET</methods>
|
||||||
<headers><pragma>no-cache</pragma></headers>
|
<headers><pragma>no-cache</pragma></headers>
|
||||||
@ -547,26 +547,26 @@
|
|||||||
<type>dynamic_query_handler</type>
|
<type>dynamic_query_handler</type>
|
||||||
<query_param_name>query</query_param_name>
|
<query_param_name>query</query_param_name>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
<routing_rule>
|
<rule>
|
||||||
<url>/predefine_query</url>
|
<url>/predefined_query</url>
|
||||||
<methods>POST,GET</methods>
|
<methods>POST,GET</methods>
|
||||||
<handler>
|
<handler>
|
||||||
<type>predefine_query_handler</type>
|
<type>predefined_query_handler</type>
|
||||||
<query>SELECT * FROM system.settings</query>
|
<query>SELECT * FROM system.settings</query>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
<routing_rule>
|
<rule>
|
||||||
<handler>
|
<handler>
|
||||||
<type>static</type>
|
<type>static</type>
|
||||||
<status>200</status>
|
<status>200</status>
|
||||||
<content_type>text/plain; charset=UTF-8</content_type>
|
<content_type>text/plain; charset=UTF-8</content_type>
|
||||||
<response_content>config://http_server_default_response</response_content>
|
<response_content>config://http_server_default_response</response_content>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
</routing_rules>
|
</http_handlers>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Uncomment to disable ClickHouse internal DNS caching. -->
|
<!-- Uncomment to disable ClickHouse internal DNS caching. -->
|
||||||
|
@ -113,11 +113,6 @@ public:
|
|||||||
compress = enable_compression;
|
compress = enable_compression;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getCompression()
|
|
||||||
{
|
|
||||||
return compress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set compression level if the compression is turned on.
|
/// Set compression level if the compression is turned on.
|
||||||
/// The setting has any effect only if HTTP headers haven't been sent yet.
|
/// The setting has any effect only if HTTP headers haven't been sent yet.
|
||||||
void setCompressionLevel(int level)
|
void setCompressionLevel(int level)
|
||||||
|
@ -37,17 +37,17 @@ def test_dynamic_query_handler():
|
|||||||
method='GET', headers={'XXX': 'xxx'}).status_code
|
method='GET', headers={'XXX': 'xxx'}).status_code
|
||||||
|
|
||||||
|
|
||||||
def test_predefine_query_handler():
|
def test_predefined_query_handler():
|
||||||
with contextlib.closing(SimpleCluster(ClickHouseCluster(__file__), "predefined_handler", "test_predefined_handler")) as cluster:
|
with contextlib.closing(SimpleCluster(ClickHouseCluster(__file__), "predefined_handler", "test_predefined_handler")) as cluster:
|
||||||
assert 404 == cluster.instance.http_request('?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code
|
assert 404 == cluster.instance.http_request('?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code
|
||||||
|
|
||||||
assert 404 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='GET', headers={'XXX': 'bad'}).status_code
|
assert 404 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='GET', headers={'XXX': 'bad'}).status_code
|
||||||
|
|
||||||
assert 404 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='POST', headers={'XXX': 'xxx'}).status_code
|
assert 404 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='POST', headers={'XXX': 'xxx'}).status_code
|
||||||
|
|
||||||
assert 500 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code
|
assert 500 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code
|
||||||
|
|
||||||
assert 'max_threads\t1\n' == cluster.instance.http_request('test_predefine_handler_get?max_threads=1&setting_name=max_threads', method='GET', headers={'XXX': 'xxx'}).content
|
assert 'max_threads\t1\n' == cluster.instance.http_request('test_predefined_handler_get?max_threads=1&setting_name=max_threads', method='GET', headers={'XXX': 'xxx'}).content
|
||||||
|
|
||||||
assert 'max_threads\t1\nmax_alter_threads\t1\n' == cluster.instance.http_request(
|
assert 'max_threads\t1\nmax_alter_threads\t1\n' == cluster.instance.http_request(
|
||||||
'query_param_with_url/max_threads?max_threads=1&max_alter_threads=1', headers={'XXX': 'max_alter_threads'}).content
|
'query_param_with_url/max_threads?max_threads=1&max_alter_threads=1', headers={'XXX': 'max_alter_threads'}).content
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<yandex>
|
<yandex>
|
||||||
<routing_rules>
|
<http_handlers>
|
||||||
<routing_rule>
|
<rule>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<url>/test_dynamic_handler_get</url>
|
<url>/test_dynamic_handler_get</url>
|
||||||
@ -10,6 +10,6 @@
|
|||||||
<type>dynamic_query_handler</type>
|
<type>dynamic_query_handler</type>
|
||||||
<query_param_name>get_dynamic_handler_query</query_param_name>
|
<query_param_name>get_dynamic_handler_query</query_param_name>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
</routing_rules>
|
</http_handlers>
|
||||||
</yandex>
|
</yandex>
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<yandex>
|
<yandex>
|
||||||
<routing_rules>
|
<http_handlers>
|
||||||
<routing_rule>
|
<rule>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<url>/test_predefine_handler_get</url>
|
<url>/test_predefined_handler_get</url>
|
||||||
<handler>
|
<handler>
|
||||||
<type>predefine_query_handler</type>
|
<type>predefined_query_handler</type>
|
||||||
<query>SELECT name, value FROM system.settings WHERE name = {setting_name:String}</query>
|
<query>SELECT name, value FROM system.settings WHERE name = {setting_name:String}</query>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
<routing_rule>
|
<rule>
|
||||||
<url><![CDATA[regex:/query_param_with_url/(?P<setting_name_1>[^/]+)]]></url>
|
<url><![CDATA[regex:/query_param_with_url/(?P<setting_name_1>[^/]+)]]></url>
|
||||||
<headers>
|
<headers>
|
||||||
<XXX><![CDATA[regex:(?P<setting_name_2>.+)]]></XXX>
|
<XXX><![CDATA[regex:(?P<setting_name_2>.+)]]></XXX>
|
||||||
</headers>
|
</headers>
|
||||||
<handler>
|
<handler>
|
||||||
<type>predefine_query_handler</type>
|
<type>predefined_query_handler</type>
|
||||||
<query>SELECT name, value FROM system.settings WHERE name = {setting_name_1:String} OR name = {setting_name_2:String}</query>
|
<query>SELECT name, value FROM system.settings WHERE name = {setting_name_1:String} OR name = {setting_name_2:String}</query>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
</routing_rules>
|
</http_handlers>
|
||||||
</yandex>
|
</yandex>
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
<yandex>
|
<yandex>
|
||||||
<test_get_config_static_handler>Test get static handler and config content</test_get_config_static_handler>
|
<test_get_config_static_handler>Test get static handler and config content</test_get_config_static_handler>
|
||||||
|
|
||||||
<routing_rules>
|
<http_handlers>
|
||||||
<routing_rule>
|
<rule>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<url>/test_get_fixed_static_handler</url>
|
<url>/test_get_fixed_static_handler</url>
|
||||||
@ -14,9 +14,9 @@
|
|||||||
<content_type>text/html; charset=UTF-8</content_type>
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
<response_content>Test get static handler and fix content</response_content>
|
<response_content>Test get static handler and fix content</response_content>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
<routing_rule>
|
<rule>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<url>/test_get_config_static_handler</url>
|
<url>/test_get_config_static_handler</url>
|
||||||
@ -24,9 +24,9 @@
|
|||||||
<type>static</type>
|
<type>static</type>
|
||||||
<response_content>config://test_get_config_static_handler</response_content>
|
<response_content>config://test_get_config_static_handler</response_content>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
<routing_rule>
|
<rule>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<url>/test_get_absolute_path_static_handler</url>
|
<url>/test_get_absolute_path_static_handler</url>
|
||||||
@ -35,9 +35,9 @@
|
|||||||
<content_type>text/html; charset=UTF-8</content_type>
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
<response_content>file:///absolute_path_file.html</response_content>
|
<response_content>file:///absolute_path_file.html</response_content>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
<routing_rule>
|
<rule>
|
||||||
<methods>GET</methods>
|
<methods>GET</methods>
|
||||||
<headers><XXX>xxx</XXX></headers>
|
<headers><XXX>xxx</XXX></headers>
|
||||||
<url>/test_get_relative_path_static_handler</url>
|
<url>/test_get_relative_path_static_handler</url>
|
||||||
@ -46,7 +46,7 @@
|
|||||||
<content_type>text/html; charset=UTF-8</content_type>
|
<content_type>text/html; charset=UTF-8</content_type>
|
||||||
<response_content>file://./relative_path_file.html</response_content>
|
<response_content>file://./relative_path_file.html</response_content>
|
||||||
</handler>
|
</handler>
|
||||||
</routing_rule>
|
</rule>
|
||||||
|
|
||||||
</routing_rules>
|
</http_handlers>
|
||||||
</yandex>
|
</yandex>
|
||||||
|
Loading…
Reference in New Issue
Block a user