Added /play handler; added a test

This commit is contained in:
Alexey Milovidov 2020-10-20 03:28:33 +03:00
parent 0af87e9598
commit a554ca5e62
8 changed files with 96 additions and 16 deletions

View File

@ -4,7 +4,7 @@ set(CLICKHOUSE_SERVER_SOURCES
) )
if (OS_LINUX) if (OS_LINUX)
set (LINK_CONFIG_LIB INTERFACE "-Wl,${WHOLE_ARCHIVE} $<TARGET_FILE:clickhouse_server_configs> -Wl,${NO_WHOLE_ARCHIVE}") set (LINK_RESOURCE_LIB INTERFACE "-Wl,${WHOLE_ARCHIVE} $<TARGET_FILE:clickhouse_server_configs> -Wl,${NO_WHOLE_ARCHIVE}")
endif () endif ()
set (CLICKHOUSE_SERVER_LINK set (CLICKHOUSE_SERVER_LINK
@ -20,7 +20,7 @@ set (CLICKHOUSE_SERVER_LINK
clickhouse_table_functions clickhouse_table_functions
string_utils string_utils
${LINK_CONFIG_LIB} ${LINK_RESOURCE_LIB}
PUBLIC PUBLIC
daemon daemon
@ -37,20 +37,20 @@ if (OS_LINUX)
# 1. Allow to run the binary without download of any other files. # 1. Allow to run the binary without download of any other files.
# 2. Allow to implement "sudo clickhouse install" tool. # 2. Allow to implement "sudo clickhouse install" tool.
foreach(CONFIG_FILE config users embedded) foreach(RESOURCE_FILE config.xml users.xml embedded.xml play.html)
set(CONFIG_OBJ ${CONFIG_FILE}.o) set(RESOURCE_OBJ ${RESOURCE_FILE}.o)
set(CONFIG_OBJS ${CONFIG_OBJS} ${CONFIG_OBJ}) set(RESOURCE_OBJS ${RESOURCE_OBJS} ${RESOURCE_OBJ})
# https://stackoverflow.com/questions/14776463/compile-and-add-an-object-file-from-a-binary-with-cmake # https://stackoverflow.com/questions/14776463/compile-and-add-an-object-file-from-a-binary-with-cmake
add_custom_command(OUTPUT ${CONFIG_OBJ} add_custom_command(OUTPUT ${RESOURCE_OBJ}
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${OBJCOPY_PATH} -I binary ${OBJCOPY_ARCH_OPTIONS} ${CONFIG_FILE}.xml ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_OBJ} COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${OBJCOPY_PATH} -I binary ${OBJCOPY_ARCH_OPTIONS} ${RESOURCE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${RESOURCE_OBJ}
COMMAND ${OBJCOPY_PATH} --rename-section .data=.rodata,alloc,load,readonly,data,contents COMMAND ${OBJCOPY_PATH} --rename-section .data=.rodata,alloc,load,readonly,data,contents
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_OBJ} ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_OBJ}) ${CMAKE_CURRENT_BINARY_DIR}/${RESOURCE_OBJ} ${CMAKE_CURRENT_BINARY_DIR}/${RESOURCE_OBJ})
set_source_files_properties(${CONFIG_OBJ} PROPERTIES EXTERNAL_OBJECT true GENERATED true) set_source_files_properties(${RESOURCE_OBJ} PROPERTIES EXTERNAL_OBJECT true GENERATED true)
endforeach(CONFIG_FILE) endforeach(RESOURCE_FILE)
add_library(clickhouse_server_configs STATIC ${CONFIG_OBJS}) add_library(clickhouse_server_configs STATIC ${RESOURCE_OBJS})
set_target_properties(clickhouse_server_configs PROPERTIES LINKER_LANGUAGE C) set_target_properties(clickhouse_server_configs PROPERTIES LINKER_LANGUAGE C)
# whole-archive prevents symbols from being discarded for unknown reason # whole-archive prevents symbols from being discarded for unknown reason

View File

@ -8,6 +8,7 @@
#include "ReplicasStatusHandler.h" #include "ReplicasStatusHandler.h"
#include "InterserverIOHTTPHandler.h" #include "InterserverIOHTTPHandler.h"
#include "PrometheusRequestHandler.h" #include "PrometheusRequestHandler.h"
#include "WebUIRequestHandler.h"
namespace DB namespace DB
@ -78,7 +79,9 @@ static inline auto createHandlersFactoryFromConfig(
for (const auto & key : keys) for (const auto & key : keys)
{ {
if (key == "defaults") if (key == "defaults")
{
addDefaultHandlersFactory(*main_handler_factory, server, async_metrics); addDefaultHandlersFactory(*main_handler_factory, server, async_metrics);
}
else if (startsWith(key, "rule")) else if (startsWith(key, "rule"))
{ {
const auto & handler_type = server.config().getString(prefix + "." + key + ".handler.type", ""); const auto & handler_type = server.config().getString(prefix + "." + key + ".handler.type", "");
@ -112,7 +115,9 @@ static inline auto createHandlersFactoryFromConfig(
static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IServer & server, const std::string & name, AsynchronousMetrics & async_metrics) static inline Poco::Net::HTTPRequestHandlerFactory * createHTTPHandlerFactory(IServer & server, const std::string & name, AsynchronousMetrics & async_metrics)
{ {
if (server.config().has("http_handlers")) if (server.config().has("http_handlers"))
{
return createHandlersFactoryFromConfig(server, name, "http_handlers", async_metrics); return createHandlersFactoryFromConfig(server, name, "http_handlers", async_metrics);
}
else else
{ {
auto factory = std::make_unique<HTTPRequestHandlerFactoryMain>(name); auto factory = std::make_unique<HTTPRequestHandlerFactoryMain>(name);
@ -168,6 +173,10 @@ void addCommonDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IS
auto replicas_status_handler = std::make_unique<HandlingRuleHTTPHandlerFactory<ReplicasStatusHandler>>(server); auto replicas_status_handler = std::make_unique<HandlingRuleHTTPHandlerFactory<ReplicasStatusHandler>>(server);
replicas_status_handler->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest(); replicas_status_handler->attachNonStrictPath("/replicas_status")->allowGetAndHeadRequest();
factory.addHandler(replicas_status_handler.release()); factory.addHandler(replicas_status_handler.release());
auto web_ui_handler = std::make_unique<HandlingRuleHTTPHandlerFactory<WebUIRequestHandler>>(server, "play.html");
web_ui_handler->attachNonStrictPath("/play")->allowGetAndHeadRequest();
factory.addHandler(web_ui_handler.release());
} }
void addDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IServer & server, AsynchronousMetrics & async_metrics) void addDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IServer & server, AsynchronousMetrics & async_metrics)

View File

@ -1,4 +1,5 @@
#include "StaticRequestHandler.h" #include "StaticRequestHandler.h"
#include "IServer.h"
#include "HTTPHandlerFactory.h" #include "HTTPHandlerFactory.h"
#include "HTTPHandlerRequestFilter.h" #include "HTTPHandlerRequestFilter.h"
@ -17,6 +18,8 @@
#include <Poco/Net/HTTPServerRequest.h> #include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h> #include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h> #include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Util/LayeredConfiguration.h>
namespace DB namespace DB
{ {

View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include "IServer.h"
#include <Poco/Net/HTTPRequestHandler.h> #include <Poco/Net/HTTPRequestHandler.h>
#include <Common/StringUtils/StringUtils.h>
#include <common/types.h> #include <common/types.h>
#include <IO/WriteBuffer.h>
namespace DB namespace DB
{ {
class IServer;
class WriteBuffer;
/// Response with custom string. Can be used for browser. /// Response with custom string. Can be used for browser.
class StaticRequestHandler : public Poco::Net::HTTPRequestHandler class StaticRequestHandler : public Poco::Net::HTTPRequestHandler
{ {
@ -22,7 +21,11 @@ private:
String response_expression; String response_expression;
public: public:
StaticRequestHandler(IServer & server, const String & expression, int status_ = 200, const String & content_type_ = "text/html; charset=UTF-8"); StaticRequestHandler(
IServer & server,
const String & expression,
int status_ = 200,
const String & content_type_ = "text/html; charset=UTF-8");
void writeResponse(WriteBuffer & out); void writeResponse(WriteBuffer & out);

View File

@ -0,0 +1,35 @@
#include "WebUIRequestHandler.h"
#include "IServer.h"
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Util/LayeredConfiguration.h>
#include <IO/HTTPCommon.h>
#include <common/getResource.h>
namespace DB
{
WebUIRequestHandler::WebUIRequestHandler(IServer & server_, std::string resource_name_)
: server(server_), resource_name(std::move(resource_name_))
{
}
void WebUIRequestHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response)
{
auto keep_alive_timeout = server.config().getUInt("keep_alive_timeout", 10);
response.setContentType("text/html; charset=UTF-8");
if (request.getVersion() == Poco::Net::HTTPServerRequest::HTTP_1_1)
response.setChunkedTransferEncoding(true);
setResponseDefaultHeaders(response, keep_alive_timeout);
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK);
response.send() << getResource(resource_name);
}
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <Poco/Net/HTTPRequestHandler.h>
namespace DB
{
class IServer;
/// Response with HTML page that allow to send queries and show results in browser.
class WebUIRequestHandler : public Poco::Net::HTTPRequestHandler
{
private:
IServer & server;
std::string resource_name;
public:
WebUIRequestHandler(IServer & server_, std::string resource_name_);
void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override;
};
}

View File

@ -0,0 +1 @@
🌞

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
. "$CURDIR"/../shell_config.sh
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_PORT_HTTP_PROTO}://${CLICKHOUSE_HOST}:${CLICKHOUSE_PORT_HTTP}/play" | grep -o '🌞'