-
Notifications
You must be signed in to change notification settings - Fork 9k
Expand file tree
/
Copy pathHTTPHandlerFactory.h
More file actions
156 lines (132 loc) · 5.88 KB
/
Copy pathHTTPHandlerFactory.h
File metadata and controls
156 lines (132 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once
#include <Server/HTTP/HTTPRequestHandlerFactory.h>
#include <Server/HTTPHandlerRequestFilter.h>
#include <Server/HTTPRequestHandlerFactoryMain.h>
#include <Common/StringUtils.h>
#include <Poco/Util/AbstractConfiguration.h>
namespace DB
{
class IServer;
class AsynchronousMetrics;
template <typename TEndpoint>
class HandlingRuleHTTPHandlerFactory : public HTTPRequestHandlerFactory
{
public:
using Filter = std::function<bool(const HTTPServerRequest &)>;
using Creator = std::function<std::unique_ptr<TEndpoint>()>;
explicit HandlingRuleHTTPHandlerFactory(Creator && creator_)
: creator(std::move(creator_))
{}
explicit HandlingRuleHTTPHandlerFactory(IServer & server)
{
creator = [&server]() -> std::unique_ptr<TEndpoint> { return std::make_unique<TEndpoint>(server); };
}
void 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);
};
}
void addFilters(std::vector<Filter> filters)
{
for (auto & cur_filter : filters)
addFilter(std::move(cur_filter));
}
void addFiltersFromConfig(const Poco::Util::AbstractConfiguration & config, const std::string & prefix)
{
addFilters(extractHTTPRequestFiltersFromConfig(config, prefix));
}
void attachStrictPath(const String & strict_path)
{
addFilter([strict_path](const auto & request) { return request.getURI() == strict_path; });
}
void attachNonStrictPath(const String & non_strict_path)
{
addFilter([non_strict_path](const auto & request) { return startsWith(request.getURI(), non_strict_path); });
}
/// Handle GET or HEAD endpoint on specified path
void allowGetAndHeadRequest()
{
addFilter([](const auto & request)
{
return request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD;
});
}
/// Handle GET, HEAD or POST endpoint on specified path
void allowGetHeadAndPostRequest()
{
addFilter([](const auto & request)
{
return request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST;
});
}
/// Handle Post request or (Get or Head) with params or OPTIONS requests
void allowPostAndGetParamsAndOptionsRequest()
{
addFilter([](const auto & request)
{
return (request.getURI().contains('?')
&& (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD))
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST;
});
}
void allowRESTMethods()
{
addFilter([](const auto & request)
{
return request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE;
});
}
std::unique_ptr<HTTPRequestHandler> createRequestHandler(const HTTPServerRequest & request) override
{
/// A rule with no filters (a config rule with only `handler` and no match conditions) matches every request.
return (!filter || 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,
std::unordered_map<String, String> & common_headers);
HTTPRequestHandlerFactoryPtr createDynamicHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix,
std::unordered_map<String, String> & common_headers,
const std::optional<String> & default_session_user = {});
HTTPRequestHandlerFactoryPtr createPredefinedHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix,
std::unordered_map<String, String> & common_headers,
const std::optional<String> & default_session_user = {});
HTTPRequestHandlerFactoryPtr createReplicasStatusHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix,
std::unordered_map<String, String> & common_headers);
/// @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)
/// @param http_handlers_key - config key for custom http_handlers (default: "http_handlers")
/// @param protocol_name - composable protocol name this factory serves; used to scope SQL-defined
/// handlers that specify a PROTOCOL. Empty for legacy http_port/https_port.
/// @param default_session_user - overrides the `default_session_user` server setting for this listener
HTTPRequestHandlerFactoryPtr createHandlerFactory(IServer & server,
const Poco::Util::AbstractConfiguration & config,
AsynchronousMetrics & async_metrics,
const std::string & name,
const std::string & http_handlers_key = {},
const std::string & protocol_name = {},
const std::optional<String> & default_session_user = {});
}