diff --git a/programs/server/HTTPHandler.cpp b/programs/server/HTTPHandler.cpp index e1d82dc7735..6175e3e57c2 100644 --- a/programs/server/HTTPHandler.cpp +++ b/programs/server/HTTPHandler.cpp @@ -755,15 +755,15 @@ std::string DynamicQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request return full_query; } -PredefineQueryHandler::PredefineQueryHandler( - IServer & server, const NameSet & receive_params_, const std::string & predefine_query_ +PredefinedQueryHandler::PredefinedQueryHandler( + IServer & server, const NameSet & receive_params_, const std::string & predefined_query_ , const std::optional & url_regex_, const std::unordered_map & header_name_with_regex_) - : HTTPHandler(server, "PredefineQueryHandler"), receive_params(receive_params_), predefine_query(predefine_query_) + : HTTPHandler(server, "PredefinedQueryHandler"), receive_params(receive_params_), predefined_query(predefined_query_) , url_regex(url_regex_), header_name_with_capture_regex(header_name_with_regex_) { } -bool PredefineQueryHandler::customizeQueryParam(Context & context, const std::string & key, const std::string & value) +bool PredefinedQueryHandler::customizeQueryParam(Context & context, const std::string & key, const std::string & value) { if (receive_params.count(key)) { @@ -774,7 +774,7 @@ bool PredefineQueryHandler::customizeQueryParam(Context & context, const std::st return false; } -void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & request, DB::Context & context) +void PredefinedQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & request, DB::Context & context) { /// If in the configuration file, the handler's header is regex and contains named capture group /// We will extract regex named capture groups as query parameters @@ -784,7 +784,7 @@ void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & requ auto compiled_regex = std::make_shared(regex); if (!compiled_regex->ok()) - throw Exception("cannot compile re2: " + regex + " for routing_rule, error: " + compiled_regex->error() + + throw Exception("cannot compile re2: " + regex + " for http handling rule, error: " + compiled_regex->error() + ". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP); int num_captures = compiled_regex->NumberOfCapturingGroups() + 1; @@ -816,7 +816,7 @@ void PredefineQueryHandler::customizeContext(Poco::Net::HTTPServerRequest & requ } } -std::string PredefineQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request, HTMLForm & params, Context & context) +std::string PredefinedQueryHandler::getQuery(Poco::Net::HTTPServerRequest & request, HTMLForm & params, Context & context) { if (unlikely(startsWith(request.getContentType(), "multipart/form-data"))) { @@ -825,13 +825,13 @@ std::string PredefineQueryHandler::getQuery(Poco::Net::HTTPServerRequest & reque params.load(request, request.stream(), handler); } - return predefine_query; + return predefined_query; } Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix) { std::string query_param_name = server.config().getString(config_prefix + ".handler.query_param_name", "query"); - return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory(server, std::move(query_param_name)), server.config(), config_prefix); + return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory(server, std::move(query_param_name)), server.config(), config_prefix); } static inline bool capturingNamedQueryParam(NameSet receive_params, const std::string & expression) @@ -839,7 +839,7 @@ static inline bool capturingNamedQueryParam(NameSet receive_params, const std::s auto compiled_regex = std::make_shared(expression); if (!compiled_regex->ok()) - throw Exception("Cannot compile re2: " + expression + " for routing_rule, error: " + + throw Exception("Cannot compile re2: " + expression + " for http handling rule, error: " + compiled_regex->error() + ". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP); const auto & capturing_names = compiled_regex->NamedCapturingGroups(); @@ -850,15 +850,15 @@ static inline bool capturingNamedQueryParam(NameSet receive_params, const std::s }); } -Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & server, const std::string & config_prefix) +Poco::Net::HTTPRequestHandlerFactory * createPredefinedHandlerFactory(IServer & server, const std::string & config_prefix) { Poco::Util::AbstractConfiguration & configuration = server.config(); if (!configuration.has(config_prefix + ".handler.query")) throw Exception("There is no path '" + config_prefix + ".handler.query" + "' in configuration file.", ErrorCodes::NO_ELEMENTS_IN_CONFIG); - std::string predefine_query = configuration.getString(config_prefix + ".handler.query"); - NameSet analyze_receive_params = analyzeReceiveQueryParams(predefine_query); + std::string predefined_query = configuration.getString(config_prefix + ".handler.query"); + NameSet analyze_receive_params = analyzeReceiveQueryParams(predefined_query); std::unordered_map headers_name_with_regex; Poco::Util::AbstractConfiguration::Keys headers_name; @@ -884,13 +884,13 @@ Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & s url_expression = url_expression.substr(6); if (capturingNamedQueryParam(analyze_receive_params, url_expression)) - return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory( - server, std::move(analyze_receive_params), std::move(predefine_query), std::optional(url_expression), + return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory( + server, std::move(analyze_receive_params), std::move(predefined_query), std::optional(url_expression), std::move(headers_name_with_regex)), configuration, config_prefix); } - return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory( - server, std::move(analyze_receive_params), std::move(predefine_query), std::optional{} ,std::move(headers_name_with_regex)), + return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory( + server, std::move(analyze_receive_params), std::move(predefined_query), std::optional{} ,std::move(headers_name_with_regex)), configuration, config_prefix); } diff --git a/programs/server/HTTPHandler.h b/programs/server/HTTPHandler.h index 39167747358..0049ac30ccb 100644 --- a/programs/server/HTTPHandler.h +++ b/programs/server/HTTPHandler.h @@ -29,7 +29,7 @@ public: void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override; /// This method is called right before the query execution. - virtual void customizeContext(Poco::Net::HTTPServerRequest & request, Context & /* context */) {} + virtual void customizeContext(Poco::Net::HTTPServerRequest & /*request*/, Context & /* context */) {} virtual bool customizeQueryParam(Context & context, const std::string & key, const std::string & value) = 0; @@ -96,16 +96,16 @@ public: bool customizeQueryParam(Context &context, const std::string &key, const std::string &value) override; }; -class PredefineQueryHandler : public HTTPHandler +class PredefinedQueryHandler : public HTTPHandler { private: NameSet receive_params; - std::string predefine_query; + std::string predefined_query; std::optional url_regex; std::unordered_map header_name_with_capture_regex; public: - explicit PredefineQueryHandler( - IServer & server, const NameSet & receive_params_, const std::string & predefine_query_ + explicit PredefinedQueryHandler( + IServer & server, const NameSet & receive_params_, const std::string & predefined_query_ , const std::optional & url_regex_, const std::unordered_map & header_name_with_regex_); virtual void customizeContext(Poco::Net::HTTPServerRequest & request, Context & context) override; diff --git a/programs/server/HTTPHandlerFactory.cpp b/programs/server/HTTPHandlerFactory.cpp index 3e6d21f7455..a576c4a781c 100644 --- a/programs/server/HTTPHandlerFactory.cpp +++ b/programs/server/HTTPHandlerFactory.cpp @@ -26,6 +26,7 @@ namespace ErrorCodes { extern const int LOGICAL_ERROR; extern const int UNKNOWN_ELEMENT_IN_CONFIG; + extern const int INVALID_CONFIG_PARAMETER; } HTTPRequestHandlerFactoryMain::HTTPRequestHandlerFactoryMain(const std::string & name_) @@ -63,7 +64,10 @@ Poco::Net::HTTPRequestHandler * HTTPRequestHandlerFactoryMain::createRequestHand HTTPRequestHandlerFactoryMain::~HTTPRequestHandlerFactoryMain() { while (!child_factories.empty()) - delete child_factories.back(), child_factories.pop_back(); + { + delete child_factories.back(); + child_factories.pop_back(); + } } HTTPRequestHandlerFactoryMain::TThis * HTTPRequestHandlerFactoryMain::addHandler(Poco::Net::HTTPRequestHandlerFactory * child_factory) @@ -83,8 +87,8 @@ static inline auto createHandlersFactoryFromConfig(IServer & server, const std:: for (const auto & key : keys) { - if (!startsWith(key, "routing_rule")) - throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'routing_rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG); + if (!startsWith(key, "rule")) + throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG); const auto & handler_type = server.config().getString(prefix + "." + key + ".handler.type", ""); @@ -92,10 +96,14 @@ static inline auto createHandlersFactoryFromConfig(IServer & server, const std:: main_handler_factory->addHandler(createStaticHandlerFactory(server, prefix + "." + key)); else if (handler_type == "dynamic_query_handler") main_handler_factory->addHandler(createDynamicHandlerFactory(server, prefix + "." + key)); - else if (handler_type == "predefine_query_handler") - main_handler_factory->addHandler(createPredefineHandlerFactory(server, prefix + "." + key)); + else if (handler_type == "predefined_query_handler") + main_handler_factory->addHandler(createPredefinedHandlerFactory(server, prefix + "." + key)); + else if (handler_type.empty()) + throw Exception("Handler type in config is not specified here: " + + prefix + "." + key + ".handler.type", ErrorCodes::INVALID_CONFIG_PARAMETER); else - throw Exception("Unknown element in config: " + prefix + "." + key + ", must be 'routing_rule'", ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG); + throw Exception("Unknown handler type '" + handler_type +"' in config here: " + + prefix + "." + key + ".handler.type",ErrorCodes::INVALID_CONFIG_PARAMETER); } return main_handler_factory; @@ -112,21 +120,21 @@ static const auto root_response_expression = "config://http_server_default_respo static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IServer & server, const std::string & name, AsynchronousMetrics & async_metrics) { - if (server.config().has("routing_rules")) - return createHandlersFactoryFromConfig(server, name, "routing_rules"); + if (server.config().has("http_handlers")) + return createHandlersFactoryFromConfig(server, name, "http_handlers"); else { auto factory = (new HTTPRequestHandlerFactoryMain(name)) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server, root_response_expression)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server, root_response_expression)) ->attachStrictPath("/")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server, ping_response_expression)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server, ping_response_expression)) ->attachStrictPath("/ping")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server)) ->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server, "query"))->allowPostAndGetParamsRequest()); + ->addHandler((new HandlingRuleHTTPHandlerFactory(server, "query"))->allowPostAndGetParamsRequest()); if (server.config().has("prometheus") && server.config().getInt("prometheus.port", 0) == 0) - factory->addHandler((new RoutingRuleHTTPHandlerFactory( + factory->addHandler((new HandlingRuleHTTPHandlerFactory( server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics))) ->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest()); @@ -137,13 +145,13 @@ static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IS static inline Poco::Net::HTTPRequestHandlerFactory * createInterserverHTTPHandlerFactory(IServer & server, const std::string & name) { return (new HTTPRequestHandlerFactoryMain(name)) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server, root_response_expression)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server, root_response_expression)) ->attachStrictPath("/")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server, ping_response_expression)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server, ping_response_expression)) ->attachStrictPath("/ping")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server)) + ->addHandler((new HandlingRuleHTTPHandlerFactory(server)) ->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest()) - ->addHandler((new RoutingRuleHTTPHandlerFactory(server))->allowPostAndGetParamsRequest()); + ->addHandler((new HandlingRuleHTTPHandlerFactory(server))->allowPostAndGetParamsRequest()); } Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name) @@ -153,11 +161,11 @@ Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, As else if (name == "InterserverIOHTTPHandler-factory" || name == "InterserverIOHTTPSHandler-factory") return createInterserverHTTPHandlerFactory(server, name); else if (name == "PrometheusHandler-factory") - return (new HTTPRequestHandlerFactoryMain(name))->addHandler((new RoutingRuleHTTPHandlerFactory( + return (new HTTPRequestHandlerFactoryMain(name))->addHandler((new HandlingRuleHTTPHandlerFactory( server, PrometheusMetricsWriter(server.config(), "prometheus", async_metrics))) ->attachStrictPath(server.config().getString("prometheus.endpoint", "/metrics"))->allowGetAndHeadRequest()); throw Exception("LOGICAL ERROR: Unknown HTTP handler factory name.", ErrorCodes::LOGICAL_ERROR); } -} \ No newline at end of file +} diff --git a/programs/server/HTTPHandlerFactory.h b/programs/server/HTTPHandlerFactory.h index a3582c48618..cf061e5b626 100644 --- a/programs/server/HTTPHandlerFactory.h +++ b/programs/server/HTTPHandlerFactory.h @@ -13,7 +13,7 @@ namespace DB { /// Handle request using child handlers -class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory +class HTTPRequestHandlerFactoryMain : public Poco::Net::HTTPRequestHandlerFactory, boost::noncopyable { private: using TThis = HTTPRequestHandlerFactoryMain; @@ -34,14 +34,14 @@ public: }; template -class RoutingRuleHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory +class HandlingRuleHTTPHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { public: - using TThis = RoutingRuleHTTPHandlerFactory; + using TThis = HandlingRuleHTTPHandlerFactory; using Filter = std::function; template - RoutingRuleHTTPHandlerFactory(TArgs &&... args) + HandlingRuleHTTPHandlerFactory(TArgs &&... args) { creator = [args = std::tuple(std::forward(args) ...)]() { @@ -107,7 +107,7 @@ Poco::Net::HTTPRequestHandlerFactory * createStaticHandlerFactory(IServer & serv Poco::Net::HTTPRequestHandlerFactory * createDynamicHandlerFactory(IServer & server, const std::string & config_prefix); -Poco::Net::HTTPRequestHandlerFactory * createPredefineHandlerFactory(IServer & server, const std::string & config_prefix); +Poco::Net::HTTPRequestHandlerFactory * createPredefinedHandlerFactory(IServer & server, const std::string & config_prefix); Poco::Net::HTTPRequestHandlerFactory * createHandlerFactory(IServer & server, AsynchronousMetrics & async_metrics, const std::string & name); diff --git a/programs/server/HTTPHandlerRequestFilter.h b/programs/server/HTTPHandlerRequestFilter.h index 2a3b2f4bed6..13d2e17dd80 100644 --- a/programs/server/HTTPHandlerRequestFilter.h +++ b/programs/server/HTTPHandlerRequestFilter.h @@ -31,7 +31,7 @@ static inline bool checkRegexExpression(const StringRef & match_str, const Strin auto compiled_regex = std::make_shared(regex); if (!compiled_regex->ok()) - throw Exception("cannot compile re2: " + expression.toString() + " for routing_rule, error: " + compiled_regex->error() + + throw Exception("cannot compile re2: " + expression.toString() + " for http handling rule, error: " + compiled_regex->error() + ". Look at https://github.com/google/re2/wiki/Syntax for reference.", ErrorCodes::CANNOT_COMPILE_REGEXP); int num_captures = compiled_regex->NumberOfCapturingGroups() + 1; @@ -99,7 +99,7 @@ static inline auto headersFilter(Poco::Util::AbstractConfiguration & config, con template static inline Poco::Net::HTTPRequestHandlerFactory * addFiltersFromConfig( - RoutingRuleHTTPHandlerFactory * factory, Poco::Util::AbstractConfiguration & config, const std::string & prefix) + HandlingRuleHTTPHandlerFactory * factory, Poco::Util::AbstractConfiguration & config, const std::string & prefix) { Poco::Util::AbstractConfiguration::Keys filters_type; config.keys(prefix, filters_type); diff --git a/programs/server/StaticRequestHandler.cpp b/programs/server/StaticRequestHandler.cpp index ff57a4764e0..22f32e6a0e7 100644 --- a/programs/server/StaticRequestHandler.cpp +++ b/programs/server/StaticRequestHandler.cpp @@ -140,7 +140,7 @@ void StaticRequestHandler::writeResponse(WriteBuffer & out) else if (startsWith(response_expression, config_prefix)) { if (response_expression.size() <= config_prefix.size()) - throw Exception( "Static routing rule handler must contain a complete configuration path, for example: config://config_key", + throw Exception( "Static handling rule handler must contain a complete configuration path, for example: config://config_key", ErrorCodes::INVALID_CONFIG_PARAMETER); const auto & config_path = response_expression.substr(config_prefix.size(), response_expression.size() - config_prefix.size()); @@ -161,7 +161,7 @@ Poco::Net::HTTPRequestHandlerFactory * createStaticHandlerFactory(IServer & serv std::string response_content = server.config().getRawString(config_prefix + ".handler.response_content", "Ok.\n"); std::string response_content_type = server.config().getString(config_prefix + ".handler.content_type", "text/plain; charset=UTF-8"); - return addFiltersFromConfig(new RoutingRuleHTTPHandlerFactory( + return addFiltersFromConfig(new HandlingRuleHTTPHandlerFactory( server, std::move(response_content), std::move(status), std::move(response_content_type)), server.config(), config_prefix); } diff --git a/programs/server/config.xml b/programs/server/config.xml index a53b0f4ff48..7ed2ead3703 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -525,21 +525,21 @@ --> - diff --git a/src/IO/WriteBufferFromHTTPServerResponse.h b/src/IO/WriteBufferFromHTTPServerResponse.h index c10288fff9f..ffa36c11c5b 100644 --- a/src/IO/WriteBufferFromHTTPServerResponse.h +++ b/src/IO/WriteBufferFromHTTPServerResponse.h @@ -113,11 +113,6 @@ public: compress = enable_compression; } - bool getCompression() - { - return compress; - } - /// Set compression level if the compression is turned on. /// The setting has any effect only if HTTP headers haven't been sent yet. void setCompressionLevel(int level) diff --git a/tests/integration/test_http_handlers_config/test.py b/tests/integration/test_http_handlers_config/test.py index d152c7e329a..407733e9f5d 100644 --- a/tests/integration/test_http_handlers_config/test.py +++ b/tests/integration/test_http_handlers_config/test.py @@ -37,17 +37,17 @@ def test_dynamic_query_handler(): method='GET', headers={'XXX': 'xxx'}).status_code -def test_predefine_query_handler(): +def test_predefined_query_handler(): with contextlib.closing(SimpleCluster(ClickHouseCluster(__file__), "predefined_handler", "test_predefined_handler")) as cluster: assert 404 == cluster.instance.http_request('?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code - assert 404 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='GET', headers={'XXX': 'bad'}).status_code + assert 404 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='GET', headers={'XXX': 'bad'}).status_code - assert 404 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='POST', headers={'XXX': 'xxx'}).status_code + assert 404 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='POST', headers={'XXX': 'xxx'}).status_code - assert 500 == cluster.instance.http_request('test_predefine_handler_get?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code + assert 500 == cluster.instance.http_request('test_predefined_handler_get?max_threads=1', method='GET', headers={'XXX': 'xxx'}).status_code - assert 'max_threads\t1\n' == cluster.instance.http_request('test_predefine_handler_get?max_threads=1&setting_name=max_threads', method='GET', headers={'XXX': 'xxx'}).content + assert 'max_threads\t1\n' == cluster.instance.http_request('test_predefined_handler_get?max_threads=1&setting_name=max_threads', method='GET', headers={'XXX': 'xxx'}).content assert 'max_threads\t1\nmax_alter_threads\t1\n' == cluster.instance.http_request( 'query_param_with_url/max_threads?max_threads=1&max_alter_threads=1', headers={'XXX': 'max_alter_threads'}).content diff --git a/tests/integration/test_http_handlers_config/test_dynamic_handler/config.xml b/tests/integration/test_http_handlers_config/test_dynamic_handler/config.xml index 7fe152d576e..9e0af81ab99 100644 --- a/tests/integration/test_http_handlers_config/test_dynamic_handler/config.xml +++ b/tests/integration/test_http_handlers_config/test_dynamic_handler/config.xml @@ -1,8 +1,8 @@ - - + + xxx GET /test_dynamic_handler_get @@ -10,6 +10,6 @@ dynamic_query_handler get_dynamic_handler_query - - + + diff --git a/tests/integration/test_http_handlers_config/test_predefined_handler/config.xml b/tests/integration/test_http_handlers_config/test_predefined_handler/config.xml index 8ac4b2950e6..7ed6d29c613 100644 --- a/tests/integration/test_http_handlers_config/test_predefined_handler/config.xml +++ b/tests/integration/test_http_handlers_config/test_predefined_handler/config.xml @@ -1,25 +1,25 @@ - - + + GET xxx - /test_predefine_handler_get + /test_predefined_handler_get - predefine_query_handler + predefined_query_handler SELECT name, value FROM system.settings WHERE name = {setting_name:String} - - + + [^/]+)]]> .+)]]> - predefine_query_handler + predefined_query_handler SELECT name, value FROM system.settings WHERE name = {setting_name_1:String} OR name = {setting_name_2:String} - - + + diff --git a/tests/integration/test_http_handlers_config/test_static_handler/config.xml b/tests/integration/test_http_handlers_config/test_static_handler/config.xml index b1609cd055d..7938a9fd8f5 100644 --- a/tests/integration/test_http_handlers_config/test_static_handler/config.xml +++ b/tests/integration/test_http_handlers_config/test_static_handler/config.xml @@ -3,8 +3,8 @@ Test get static handler and config content - - + + GET xxx /test_get_fixed_static_handler @@ -14,9 +14,9 @@ text/html; charset=UTF-8 Test get static handler and fix content - + - + GET xxx /test_get_config_static_handler @@ -24,9 +24,9 @@ static config://test_get_config_static_handler - + - + GET xxx /test_get_absolute_path_static_handler @@ -35,9 +35,9 @@ text/html; charset=UTF-8 file:///absolute_path_file.html - + - + GET xxx /test_get_relative_path_static_handler @@ -46,7 +46,7 @@ text/html; charset=UTF-8 file://./relative_path_file.html - + - +