ClickHouse/src/Server/HTTPHandlerFactory.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

136 lines
4.7 KiB
C++
Raw Normal View History

2017-08-09 14:33:07 +00:00
#pragma once
#include <Server/HTTP/HTTPRequestHandlerFactory.h>
#include <Server/HTTPHandlerRequestFilter.h>
2022-11-10 08:23:52 +00:00
#include <Server/HTTPRequestHandlerFactoryMain.h>
2024-05-19 08:02:06 +00:00
#include <Common/StringUtils.h>
#include <Poco/Util/AbstractConfiguration.h>
2017-08-09 14:33:07 +00:00
2017-08-09 14:33:07 +00:00
namespace DB
{
namespace ErrorCodes
2017-08-09 14:33:07 +00:00
{
extern const int UNKNOWN_ELEMENT_IN_CONFIG;
}
2020-04-04 08:57:16 +00:00
class IServer;
class AsynchronousMetrics;
2020-04-04 08:57:16 +00:00
template <typename TEndpoint>
class HandlingRuleHTTPHandlerFactory : public HTTPRequestHandlerFactory
{
public:
using Filter = std::function<bool(const HTTPServerRequest &)>;
2017-08-09 14:33:07 +00:00
using Creator = std::function<std::unique_ptr<TEndpoint>()>;
explicit HandlingRuleHTTPHandlerFactory(Creator && creator_)
: creator(std::move(creator_))
{}
explicit HandlingRuleHTTPHandlerFactory(IServer & server)
2020-04-04 08:57:16 +00:00
{
creator = [&server]() -> std::unique_ptr<TEndpoint> { return std::make_unique<TEndpoint>(server); };
2020-04-04 08:57:16 +00:00
}
void addFilter(Filter cur_filter)
2020-04-04 08:57:16 +00:00
{
Filter prev_filter = filter;
filter = [prev_filter, cur_filter](const auto & request)
{
return prev_filter ? prev_filter(request) && cur_filter(request) : cur_filter(request);
};
}
void addFiltersFromConfig(const Poco::Util::AbstractConfiguration & config, const std::string & prefix)
{
Poco::Util::AbstractConfiguration::Keys filters_type;
config.keys(prefix, filters_type);
for (const auto & filter_type : filters_type)
{
if (filter_type == "handler")
continue;
if (filter_type == "url")
addFilter(urlFilter(config, prefix + ".url"));
2024-02-25 22:45:09 +00:00
else if (filter_type == "empty_query_string")
addFilter(emptyQueryStringFilter());
else if (filter_type == "headers")
addFilter(headersFilter(config, prefix + ".headers"));
else if (filter_type == "methods")
addFilter(methodsFilter(config, prefix + ".methods"));
else
throw Exception(ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG, "Unknown element in config: {}.{}", prefix, filter_type);
}
2020-04-04 08:57:16 +00:00
}
void attachStrictPath(const String & strict_path)
2020-04-04 08:57:16 +00:00
{
addFilter([strict_path](const auto & request) { return request.getURI() == strict_path; });
2020-04-04 08:57:16 +00:00
}
void attachNonStrictPath(const String & non_strict_path)
2020-04-04 08:57:16 +00:00
{
addFilter([non_strict_path](const auto & request) { return startsWith(request.getURI(), non_strict_path); });
2020-04-04 08:57:16 +00:00
}
2020-04-04 08:57:16 +00:00
/// Handle GET or HEAD endpoint on specified path
void allowGetAndHeadRequest()
2020-04-04 08:57:16 +00:00
{
addFilter([](const auto & request)
2020-04-04 08:57:16 +00:00
{
return request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD;
});
}
2021-10-06 13:09:34 +00:00
/// Handle Post request or (Get or Head) with params or OPTIONS requests
2021-09-22 10:34:48 +00:00
void allowPostAndGetParamsAndOptionsRequest()
2020-04-04 08:57:16 +00:00
{
addFilter([](const auto & request)
2020-04-04 08:57:16 +00:00
{
return (request.getURI().find('?') != std::string::npos
&& (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD))
2021-09-22 10:34:48 +00:00
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS
2020-04-04 08:57:16 +00:00
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST;
});
}
std::unique_ptr<HTTPRequestHandler> createRequestHandler(const HTTPServerRequest & request) override
2020-04-04 08:57:16 +00:00
{
return filter(request) ? creator() : nullptr;
}
private:
Filter filter;
std::function<std::unique_ptr<HTTPRequestHandler> ()> creator;
};
HTTPRequestHandlerFactoryPtr createStaticHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix);
2020-04-04 08:57:16 +00:00
HTTPRequestHandlerFactoryPtr createDynamicHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix);
2020-04-04 08:57:16 +00:00
HTTPRequestHandlerFactoryPtr createPredefinedHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix);
HTTPRequestHandlerFactoryPtr createReplicasStatusHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix);
/// @param server - used in handlers to check IServer::isCancelled()
/// @param config - not the same as server.config(), since it can be newer
/// @param async_metrics - used for prometheus (in case of prometheus.asynchronous_metrics=true)
HTTPRequestHandlerFactoryPtr createHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
AsynchronousMetrics & async_metrics,
const std::string & name);
2017-08-09 14:33:07 +00:00
}