1 | #pragma once |
---|---|
2 | |
3 | #include <Poco/Net/HTTPRequestHandlerFactory.h> |
4 | #include <Poco/Net/HTTPServerRequest.h> |
5 | #include <Poco/Net/HTTPServerResponse.h> |
6 | #include <common/logger_useful.h> |
7 | #include "IServer.h" |
8 | #include "HTTPHandler.h" |
9 | #include "InterserverIOHTTPHandler.h" |
10 | #include "NotFoundHandler.h" |
11 | #include "PingRequestHandler.h" |
12 | #include "PrometheusRequestHandler.h" |
13 | #include "ReplicasStatusHandler.h" |
14 | #include "RootRequestHandler.h" |
15 | |
16 | |
17 | namespace DB |
18 | { |
19 | |
20 | /// Handle request using child handlers |
21 | class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory |
22 | { |
23 | private: |
24 | using TThis = HTTPRequestHandlerFactoryMain; |
25 | |
26 | IServer & server; |
27 | Logger * log; |
28 | std::string name; |
29 | |
30 | std::vector<std::unique_ptr<Poco::Net::HTTPRequestHandlerFactory>> child_handler_factories; |
31 | |
32 | public: |
33 | HTTPRequestHandlerFactoryMain(IServer & server_, const std::string & name_); |
34 | |
35 | Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override; |
36 | |
37 | template <typename T, typename... TArgs> |
38 | TThis * addHandler(TArgs &&... args) |
39 | { |
40 | child_handler_factories.emplace_back(std::make_unique<T>(server, std::forward<TArgs>(args)...)); |
41 | return this; |
42 | } |
43 | }; |
44 | |
45 | |
46 | /// Handle POST or GET with params |
47 | template <typename HandleType> |
48 | class HTTPQueryRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory |
49 | { |
50 | private: |
51 | IServer & server; |
52 | |
53 | public: |
54 | HTTPQueryRequestHandlerFactory(IServer & server_) : server(server_) {} |
55 | |
56 | Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override |
57 | { |
58 | if (request.getURI().find('?') != std::string::npos || request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) |
59 | return new HandleType(server); |
60 | return nullptr; |
61 | } |
62 | }; |
63 | |
64 | |
65 | /// Handle GET or HEAD endpoint on specified path |
66 | template <typename TGetEndpoint> |
67 | class HTTPGetRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory |
68 | { |
69 | private: |
70 | IServer & server; |
71 | public: |
72 | HTTPGetRequestHandlerFactory(IServer & server_) : server(server_) {} |
73 | |
74 | Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override |
75 | { |
76 | auto & method = request.getMethod(); |
77 | if (!(method == Poco::Net::HTTPRequest::HTTP_GET || method == Poco::Net::HTTPRequest::HTTP_HEAD)) |
78 | return nullptr; |
79 | |
80 | auto & uri = request.getURI(); |
81 | bool uri_match = TGetEndpoint::strict_path ? uri == TGetEndpoint::path : startsWith(uri, TGetEndpoint::path); |
82 | if (uri_match) |
83 | return new typename TGetEndpoint::HandleType(server); |
84 | |
85 | return nullptr; |
86 | } |
87 | }; |
88 | |
89 | |
90 | struct RootEndpoint |
91 | { |
92 | static constexpr auto path = "/"; |
93 | static constexpr auto strict_path = true; |
94 | using HandleType = RootRequestHandler; |
95 | }; |
96 | |
97 | struct PingEndpoint |
98 | { |
99 | static constexpr auto path = "/ping"; |
100 | static constexpr auto strict_path = true; |
101 | using HandleType = PingRequestHandler; |
102 | }; |
103 | |
104 | struct ReplicasStatusEndpoint |
105 | { |
106 | static constexpr auto path = "/replicas_status"; |
107 | static constexpr auto strict_path = false; |
108 | using HandleType = ReplicasStatusHandler; |
109 | }; |
110 | |
111 | using HTTPRootRequestHandlerFactory = HTTPGetRequestHandlerFactory<RootEndpoint>; |
112 | using HTTPPingRequestHandlerFactory = HTTPGetRequestHandlerFactory<PingEndpoint>; |
113 | using HTTPReplicasStatusRequestHandlerFactory = HTTPGetRequestHandlerFactory<ReplicasStatusEndpoint>; |
114 | |
115 | template <typename HandleType> |
116 | HTTPRequestHandlerFactoryMain * createDefaultHandlerFatory(IServer & server, const std::string & name) |
117 | { |
118 | auto handlerFactory = new HTTPRequestHandlerFactoryMain(server, name); |
119 | handlerFactory->addHandler<HTTPRootRequestHandlerFactory>() |
120 | ->addHandler<HTTPPingRequestHandlerFactory>() |
121 | ->addHandler<HTTPReplicasStatusRequestHandlerFactory>() |
122 | ->addHandler<HTTPQueryRequestHandlerFactory<HandleType>>(); |
123 | return handlerFactory; |
124 | } |
125 | |
126 | |
127 | } |
128 |