ClickHouse/programs/server/HTTPHandlerFactory.h

114 lines
3.6 KiB
C++
Raw Normal View History

2017-08-09 14:33:07 +00:00
#pragma once
2020-04-04 08:57:16 +00:00
#include "IServer.h"
#include <common/logger_useful.h>
#include <Common/StringUtils/StringUtils.h>
2017-08-09 14:33:07 +00:00
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
2020-04-03 09:09:19 +00:00
#include <Poco/Net/HTTPRequestHandlerFactory.h>
2017-08-09 14:33:07 +00:00
namespace DB
{
2020-04-04 08:57:16 +00:00
/// Handle request using child handlers
class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory
2017-08-09 14:33:07 +00:00
{
private:
2020-04-04 08:57:16 +00:00
using TThis = HTTPRequestHandlerFactoryMain;
IServer & server;
2020-04-03 09:09:19 +00:00
Logger * log;
std::string name;
2020-04-04 08:57:16 +00:00
std::vector<Poco::Net::HTTPRequestHandlerFactory *> child_handler_factories;
public:
~HTTPRequestHandlerFactoryMain();
2020-04-04 08:57:16 +00:00
HTTPRequestHandlerFactoryMain(IServer & server_, const std::string & name_);
TThis * addHandler(Poco::Net::HTTPRequestHandlerFactory * child_factory);
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override;
};
template <typename TEndpoint>
class RoutingRuleHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
public:
2020-04-04 08:57:16 +00:00
using TThis = RoutingRuleHTTPHandlerFactory<TEndpoint>;
using Filter = std::function<bool(const Poco::Net::HTTPServerRequest &)>;
2017-08-09 14:33:07 +00:00
2020-04-04 08:57:16 +00:00
template <typename... TArgs>
RoutingRuleHTTPHandlerFactory(TArgs &&... args)
{
creator = [args = std::tuple<TArgs...>(std::forward<TArgs>(args) ...)]()
{
return std::apply([&](auto && ... endpoint_args)
{
return new TEndpoint(std::forward<decltype(endpoint_args)>(endpoint_args)...);
}, std::move(args));
};
}
2020-04-04 08:57:16 +00:00
TThis * addFilter(Filter cur_filter)
{
Filter prev_filter = filter;
filter = [prev_filter, cur_filter](const auto & request)
{
return prev_filter ? prev_filter(request) && cur_filter(request) : cur_filter(request);
};
2020-04-04 08:57:16 +00:00
return this;
}
TThis * attachStrictPath(const String & strict_path)
{
return addFilter([strict_path](const auto & request) { return request.getURI() == strict_path; });
}
TThis * attachNonStrictPath(const String & non_strict_path)
{
return addFilter([non_strict_path](const auto & request) { return startsWith(request.getURI(), non_strict_path); });
}
2020-04-04 08:57:16 +00:00
/// Handle GET or HEAD endpoint on specified path
TThis * allowGetAndHeadRequest()
{
return addFilter([](const auto & request)
{
return request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD;
});
}
/// Handle POST or GET with params
TThis * allowPostAndGetParamsRequest()
{
return addFilter([](const auto & request)
{
return request.getURI().find('?') != std::string::npos
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST;
});
}
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override
{
return filter(request) ? creator() : nullptr;
}
private:
Filter filter;
std::function<Poco::Net::HTTPRequestHandler * ()> creator;
};
2020-04-04 08:57:16 +00:00
Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, const std::string & name);
Poco::Net::HTTPRequestHandlerFactory * createStaticHandlerFactory(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);
2017-08-09 14:33:07 +00:00
}