1313#include " InterserverIOHTTPHandler.h"
1414#include " WebUIRequestHandler.h"
1515
16+ #include < iostream>
1617
1718namespace DB
1819{
@@ -31,27 +32,35 @@ class RedirectRequestHandler : public HTTPRequestHandler
3132{
3233private:
3334 std::string url;
35+ std::unordered_map<String, String> http_response_headers_override;
3436
3537public:
36- explicit RedirectRequestHandler (std::string url_)
37- : url(std::move(url_))
38+ explicit RedirectRequestHandler (std::string url_, std::unordered_map<String, String> http_response_headers_override_ = {} )
39+ : url(std::move(url_)), http_response_headers_override(http_response_headers_override_)
3840 {
3941 }
4042
4143 void handleRequest (HTTPServerRequest &, HTTPServerResponse & response, const ProfileEvents::Event &) override
4244 {
45+ applyHTTPResponseHeaders (response, http_response_headers_override);
4346 response.redirect (url);
4447 }
4548};
4649
4750HTTPRequestHandlerFactoryPtr createRedirectHandlerFactory (
4851 const Poco::Util::AbstractConfiguration & config,
49- const std::string & config_prefix)
52+ const std::string & config_prefix,
53+ std::unordered_map<String, String> common_headers)
5054{
5155 std::string url = config.getString (config_prefix + " .handler.location" );
5256
57+ auto headers = parseHTTPResponseHeadersWithCommons (config, config_prefix, common_headers);
58+
5359 auto factory = std::make_shared<HandlingRuleHTTPHandlerFactory<RedirectRequestHandler>>(
54- [my_url = std::move (url)]() { return std::make_unique<RedirectRequestHandler>(my_url); });
60+ [my_url = std::move (url), headers_override = std::move (headers)]()
61+ {
62+ return std::make_unique<RedirectRequestHandler>(my_url, headers_override);
63+ });
5564
5665 factory->addFiltersFromConfig (config, config_prefix);
5766 return factory;
@@ -78,6 +87,33 @@ static auto createPingHandlerFactory(IServer & server)
7887 return std::make_shared<HandlingRuleHTTPHandlerFactory<StaticRequestHandler>>(std::move (creator));
7988}
8089
90+ static auto createPingHandlerFactory (IServer & server, const Poco::Util::AbstractConfiguration & config, const String & config_prefix,
91+ std::unordered_map<String, String> common_headers)
92+ {
93+ auto creator = [&server,&config,config_prefix,common_headers]() -> std::unique_ptr<StaticRequestHandler>
94+ {
95+ constexpr auto ping_response_expression = " Ok.\n " ;
96+
97+ auto headers = parseHTTPResponseHeadersWithCommons (config, config_prefix, " text/html; charset=UTF-8" , common_headers);
98+
99+ return std::make_unique<StaticRequestHandler>(
100+ server, ping_response_expression, headers);
101+ };
102+ return std::make_shared<HandlingRuleHTTPHandlerFactory<StaticRequestHandler>>(std::move (creator));
103+ }
104+
105+ template <typename UIRequestHandler>
106+ static auto createWebUIHandlerFactory (IServer & server, const Poco::Util::AbstractConfiguration & config, const String & config_prefix,
107+ std::unordered_map<String, String> common_headers)
108+ {
109+ auto creator = [&server,&config,config_prefix,common_headers]() -> std::unique_ptr<UIRequestHandler>
110+ {
111+ auto headers = parseHTTPResponseHeadersWithCommons (config, config_prefix, " text/html; charset=UTF-8" , common_headers);
112+ return std::make_unique<UIRequestHandler>(server, headers);
113+ };
114+ return std::make_shared<HandlingRuleHTTPHandlerFactory<UIRequestHandler>>(std::move (creator));
115+ }
116+
81117static inline auto createHandlersFactoryFromConfig (
82118 IServer & server,
83119 const Poco::Util::AbstractConfiguration & config,
@@ -90,6 +126,19 @@ static inline auto createHandlersFactoryFromConfig(
90126 Poco::Util::AbstractConfiguration::Keys keys;
91127 config.keys (prefix, keys);
92128
129+ std::unordered_map<String, String> common_headers_override;
130+
131+ if (std::find (keys.begin (), keys.end (), " common_http_response_headers" ) != keys.end ())
132+ {
133+ auto common_headers_prefix = prefix + " .common_http_response_headers" ;
134+ Poco::Util::AbstractConfiguration::Keys headers_keys;
135+ config.keys (common_headers_prefix, headers_keys);
136+ for (const auto & header_key : headers_keys)
137+ {
138+ common_headers_override[header_key] = config.getString (common_headers_prefix + " ." + header_key);
139+ }
140+ }
141+
93142 for (const auto & key : keys)
94143 {
95144 if (key == " defaults" )
@@ -106,58 +155,75 @@ static inline auto createHandlersFactoryFromConfig(
106155
107156 if (handler_type == " static" )
108157 {
109- main_handler_factory->addHandler (createStaticHandlerFactory (server, config, prefix + " ." + key));
158+ main_handler_factory->addHandler (createStaticHandlerFactory (server, config, prefix + " ." + key, common_headers_override ));
110159 }
111160 else if (handler_type == " redirect" )
112161 {
113- main_handler_factory->addHandler (createRedirectHandlerFactory (config, prefix + " ." + key));
162+ main_handler_factory->addHandler (createRedirectHandlerFactory (config, prefix + " ." + key, common_headers_override ));
114163 }
115164 else if (handler_type == " dynamic_query_handler" )
116165 {
117- main_handler_factory->addHandler (createDynamicHandlerFactory (server, config, prefix + " ." + key));
166+ main_handler_factory->addHandler (createDynamicHandlerFactory (server, config, prefix + " ." + key, common_headers_override ));
118167 }
119168 else if (handler_type == " predefined_query_handler" )
120169 {
121- main_handler_factory->addHandler (createPredefinedHandlerFactory (server, config, prefix + " ." + key));
170+ main_handler_factory->addHandler (createPredefinedHandlerFactory (server, config, prefix + " ." + key, common_headers_override ));
122171 }
123172 else if (handler_type == " prometheus" )
124173 {
125174 main_handler_factory->addHandler (
126- createPrometheusHandlerFactoryForHTTPRule (server, config, prefix + " ." + key, async_metrics));
175+ createPrometheusHandlerFactoryForHTTPRule (server, config, prefix + " ." + key, async_metrics, common_headers_override ));
127176 }
128177 else if (handler_type == " replicas_status" )
129178 {
130- main_handler_factory->addHandler (createReplicasStatusHandlerFactory (server, config, prefix + " ." + key));
179+ main_handler_factory->addHandler (createReplicasStatusHandlerFactory (server, config, prefix + " ." + key, common_headers_override ));
131180 }
132181 else if (handler_type == " ping" )
133182 {
134- auto handler = createPingHandlerFactory (server);
135- handler->addFiltersFromConfig (config, prefix + " ." + key);
183+ const String config_prefix = prefix + " ." + key;
184+ auto handler = createPingHandlerFactory (server, config, config_prefix, common_headers_override);
185+ handler->addFiltersFromConfig (config, config_prefix);
136186 main_handler_factory->addHandler (std::move (handler));
137187 }
138188 else if (handler_type == " play" )
139189 {
140- auto handler = std::make_shared<HandlingRuleHTTPHandlerFactory< PlayWebUIRequestHandler>> (server);
190+ auto handler = createWebUIHandlerFactory< PlayWebUIRequestHandler>(server, config, prefix + " . " + key, common_headers_override );
141191 handler->addFiltersFromConfig (config, prefix + " ." + key);
142192 main_handler_factory->addHandler (std::move (handler));
143193 }
144194 else if (handler_type == " dashboard" )
145195 {
146- auto handler = std::make_shared<HandlingRuleHTTPHandlerFactory< DashboardWebUIRequestHandler>> (server);
196+ auto handler = createWebUIHandlerFactory< DashboardWebUIRequestHandler>(server, config, prefix + " . " + key, common_headers_override );
147197 handler->addFiltersFromConfig (config, prefix + " ." + key);
148198 main_handler_factory->addHandler (std::move (handler));
149199 }
150200 else if (handler_type == " binary" )
151201 {
152- auto handler = std::make_shared<HandlingRuleHTTPHandlerFactory<BinaryWebUIRequestHandler>>(server);
202+ auto handler = createWebUIHandlerFactory<BinaryWebUIRequestHandler>(server, config, prefix + " ." + key, common_headers_override);
203+ handler->addFiltersFromConfig (config, prefix + " ." + key);
204+ main_handler_factory->addHandler (std::move (handler));
205+ }
206+ else if (handler_type == " js" )
207+ {
208+ // NOTE: JavaScriptWebUIRequestHandler only makes sense for paths other then /js/uplot.js, /js/lz-string.js
209+ // because these paths are hardcoded in dashboard.html
210+ const auto & path = config.getString (prefix + " ." + key + " .url" , " " );
211+ if (path != " /js/uplot.js" && path != " /js/lz-string.js" )
212+ {
213+ throw Exception (ErrorCodes::INVALID_CONFIG_PARAMETER,
214+ " Handler type 'js' is only supported for url '/js/'. "
215+ " Configured path here: {}" , path);
216+ }
217+
218+ auto handler = createWebUIHandlerFactory<JavaScriptWebUIRequestHandler>(server, config, prefix + " ." + key, common_headers_override);
153219 handler->addFiltersFromConfig (config, prefix + " ." + key);
154220 main_handler_factory->addHandler (std::move (handler));
155221 }
156222 else
157223 throw Exception (ErrorCodes::INVALID_CONFIG_PARAMETER, " Unknown handler type '{}' in config here: {}.{}.handler.type" ,
158224 handler_type, prefix, key);
159225 }
160- else
226+ else if (key != " common_http_response_headers " )
161227 throw Exception (ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG, " Unknown element in config: "
162228 " {}.{}, must be 'rule' or 'defaults'" , prefix, key);
163229 }
0 commit comments