mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 01:25:21 +00:00
Add function getClientHTTPHeader, part 2
This commit is contained in:
parent
e195806c5b
commit
965a3ac2f3
@ -895,6 +895,7 @@ class IColumn;
|
|||||||
M(Int64, ignore_cold_parts_seconds, 0, "Only available in ClickHouse Cloud. Exclude new data parts from SELECT queries until they're either pre-warmed (see cache_populated_by_fetch) or this many seconds old. Only for Replicated-/SharedMergeTree.", 0) \
|
M(Int64, ignore_cold_parts_seconds, 0, "Only available in ClickHouse Cloud. Exclude new data parts from SELECT queries until they're either pre-warmed (see cache_populated_by_fetch) or this many seconds old. Only for Replicated-/SharedMergeTree.", 0) \
|
||||||
M(Int64, prefer_warmed_unmerged_parts_seconds, 0, "Only available in ClickHouse Cloud. If a merged part is less than this many seconds old and is not pre-warmed (see cache_populated_by_fetch), but all its source parts are available and pre-warmed, SELECT queries will read from those parts instead. Only for ReplicatedMergeTree. Note that this only checks whether CacheWarmer processed the part; if the part was fetched into cache by something else, it'll still be considered cold until CacheWarmer gets to it; if it was warmed, then evicted from cache, it'll still be considered warm.", 0) \
|
M(Int64, prefer_warmed_unmerged_parts_seconds, 0, "Only available in ClickHouse Cloud. If a merged part is less than this many seconds old and is not pre-warmed (see cache_populated_by_fetch), but all its source parts are available and pre-warmed, SELECT queries will read from those parts instead. Only for ReplicatedMergeTree. Note that this only checks whether CacheWarmer processed the part; if the part was fetched into cache by something else, it'll still be considered cold until CacheWarmer gets to it; if it was warmed, then evicted from cache, it'll still be considered warm.", 0) \
|
||||||
M(Bool, iceberg_engine_ignore_schema_evolution, false, "Ignore schema evolution in Iceberg table engine and read all data using latest schema saved on table creation. Note that it can lead to incorrect result", 0) \
|
M(Bool, iceberg_engine_ignore_schema_evolution, false, "Ignore schema evolution in Iceberg table engine and read all data using latest schema saved on table creation. Note that it can lead to incorrect result", 0) \
|
||||||
|
M(Bool, allow_get_http_client_header, false, "Allow to use the function `getClientHTTPHeader` which lets to obtain a value of an the current HTTP request's header. It is not enabled by default for security reasons, because some headers, such as `Cookie`, could contain sensitive info. Note that the `X-ClickHouse-*` and `Authentication` headers are always restricted and cannot be obtained with this function.", 0) \
|
||||||
|
|
||||||
// End of COMMON_SETTINGS
|
// End of COMMON_SETTINGS
|
||||||
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS, move obsolete settings to OBSOLETE_SETTINGS and obsolete format settings to OBSOLETE_FORMAT_SETTINGS.
|
// Please add settings related to formats into the FORMAT_FACTORY_SETTINGS, move obsolete settings to OBSOLETE_SETTINGS and obsolete format settings to OBSOLETE_FORMAT_SETTINGS.
|
||||||
|
94
src/Functions/getClientHTTPHeader.cpp
Normal file
94
src/Functions/getClientHTTPHeader.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include <Functions/IFunction.h>
|
||||||
|
#include <Functions/FunctionFactory.h>
|
||||||
|
#include <Functions/FunctionHelpers.h>
|
||||||
|
#include <DataTypes/DataTypeString.h>
|
||||||
|
#include <Columns/ColumnString.h>
|
||||||
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Core/Field.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||||
|
extern const int FUNCTION_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class FunctionGetClientHTTPHeader : public IFunction, WithContext
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FunctionGetClientHTTPHeader(ContextPtr context_)
|
||||||
|
: WithContext(context_)
|
||||||
|
{
|
||||||
|
if (!getContext()->getSettingsRef().allow_get_http_client_header)
|
||||||
|
throw Exception(ErrorCodes::FUNCTION_NOT_ALLOWED, "The function {} requires setting `allow_get_client_http_header` to be enabled.", getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
String getName() const override { return "getClientHTTPHeader"; }
|
||||||
|
|
||||||
|
bool useDefaultImplementationForConstants() const override { return true; }
|
||||||
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo &) const override { return false; }
|
||||||
|
|
||||||
|
size_t getNumberOfArguments() const override
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||||
|
{
|
||||||
|
if (!isString(arguments[0]))
|
||||||
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The argument of function {} must be String", getName());
|
||||||
|
return std::make_shared<DataTypeString>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||||
|
{
|
||||||
|
const ClientInfo & client_info = getContext()->getClientInfo();
|
||||||
|
|
||||||
|
const auto & source = arguments[0].column;
|
||||||
|
auto result = result_type->createColumn();
|
||||||
|
result->reserve(input_rows_count);
|
||||||
|
|
||||||
|
for (size_t row = 0; row < input_rows_count; ++row)
|
||||||
|
{
|
||||||
|
Field header;
|
||||||
|
source->get(row, header);
|
||||||
|
if (auto it = client_info.http_headers.find(header.get<String>()); it != client_info.http_headers.end())
|
||||||
|
result->insert(it->second);
|
||||||
|
else
|
||||||
|
result->insertDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_FUNCTION(GetClientHTTPHeader)
|
||||||
|
{
|
||||||
|
factory.registerFunction("getClientHTTPHeader",
|
||||||
|
[](ContextPtr context) { return std::make_shared<FunctionGetClientHTTPHeader>(context); },
|
||||||
|
FunctionDocumentation{
|
||||||
|
.description = R"(
|
||||||
|
Get the value of an HTTP header.
|
||||||
|
|
||||||
|
If there no such header or the current request is not performed via the HTTP interface, the function returns an empty string.
|
||||||
|
Certain HTTP headers (e.g., `Authentication` and `X-ClickHouse-*`) are restricted.
|
||||||
|
|
||||||
|
The function requires the setting `allow_get_client_http_header` to be enabled.
|
||||||
|
The setting is not enabled by default for security reasons, because some headers, such as `Cookie`, could contain sensitive info.
|
||||||
|
",
|
||||||
|
.syntax = "getClientHTTPHeader(name)",
|
||||||
|
.arguments = {{"name", "The HTTP header name (String)"}},
|
||||||
|
.returned_value = "The value of the header (String).",
|
||||||
|
.categories{"Miscellaneous"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user