跳至主要内容

HTTP 接口

HTTP 接口允许您以 REST API 的形式从任何平台和任何编程语言使用 ClickHouse。HTTP 接口比原生接口功能更有限,但它具有更好的语言支持。

默认情况下,clickhouse-server 在端口 8123 上侦听 HTTP 请求(这可以在配置文件中更改)。HTTPS 也可以启用,默认端口为 8443。

如果您发出不带参数的 GET / 请求,它将返回 200 响应代码和在 http_server_default_response 中定义的字符串,默认值为“Ok.”(末尾带换行符)

$ curl 'https://127.0.0.1:8123/'
Ok.

另请参阅:HTTP 响应代码注意事项

有时,用户操作系统上可能没有 curl 命令。在 Ubuntu 或 Debian 上,运行 sudo apt install curl。在运行示例之前,请参考此 文档 进行安装。

Web UI 可以通过以下地址访问:https://127.0.0.1:8123/play

Web UI

在健康检查脚本中使用 GET /ping 请求。此处理程序始终返回“Ok.”(末尾带换行符)。从版本 18.12.13 开始可用。另请参阅 /replicas_status 以检查副本的延迟。

$ curl 'https://127.0.0.1:8123/ping'
Ok.
$ curl 'https://127.0.0.1:8123/replicas_status'
Ok.

将请求作为 URL 的 ‘query’ 参数发送,或作为 POST 发送。或者在 ‘query’ 参数中发送查询的开头,并在 POST 中发送其余部分(稍后我们将解释为什么需要这样做)。默认情况下,URL 的大小限制为 1 MiB,这可以通过 http_max_uri_size 设置更改。

如果成功,您将收到 200 响应代码并在响应主体中收到结果。如果发生错误,您将收到 500 响应代码并在响应主体中收到错误描述文本。

使用 GET 方法时,会设置 ‘readonly’。换句话说,对于修改数据的查询,您只能使用 POST 方法。您可以将查询本身发送到 POST 主体或 URL 参数中。

示例

$ curl 'https://127.0.0.1:8123/?query=SELECT%201'
1

$ wget -nv -O- 'https://127.0.0.1:8123/?query=SELECT 1'
1

$ echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
HTTP/1.0 200 OK
Date: Wed, 27 Nov 2019 10:30:18 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
X-ClickHouse-Server-Display-Name: clickhouse.ru-central1.internal
X-ClickHouse-Query-Id: 5abe861c-239c-467f-b955-8a201abb8b7f
X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}

1

如您所见,curl 在某种程度上不太方便,因为空格必须进行 URL 编码。虽然 wget 会自动对所有内容进行编码,但我们不建议使用它,因为它在使用 keep-alive 和 Transfer-Encoding: chunked 时无法很好地处理 HTTP 1.1。

$ echo 'SELECT 1' | curl 'https://127.0.0.1:8123/' --data-binary @-
1

$ echo 'SELECT 1' | curl 'https://127.0.0.1:8123/?query=' --data-binary @-
1

$ echo '1' | curl 'https://127.0.0.1:8123/?query=SELECT' --data-binary @-
1

如果查询的一部分在参数中发送,一部分在 POST 中发送,则在这两个数据部分之间插入一个换行符。示例(此方法无效)

$ echo 'ECT 1' | curl 'https://127.0.0.1:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception

默认情况下,数据以 TabSeparated 格式返回。

您可以使用查询的 FORMAT 子句请求任何其他格式。

此外,您可以使用 ‘default_format’ URL 参数或 ‘X-ClickHouse-Format’ 标头指定除 TabSeparated 之外的默认格式。

$ echo 'SELECT 1 FORMAT Pretty' | curl 'https://127.0.0.1:8123/?' --data-binary @-
┏━━━┓
1
┡━━━┩
1
└───┘

传输数据的 POST 方法对于 INSERT 查询是必需的。在这种情况下,您可以在 URL 参数中写入查询的开头,并使用 POST 将要插入的数据传递给服务器。要插入的数据可以是,例如,来自 MySQL 的制表符分隔的转储。通过这种方式,INSERT 查询取代了来自 MySQL 的 LOAD DATA LOCAL INFILE

示例

创建表

$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'https://127.0.0.1:8123/' --data-binary @-

使用熟悉的 INSERT 查询进行数据插入

$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'https://127.0.0.1:8123/' --data-binary @-

数据可以与查询分开发送

$ echo '(4),(5),(6)' | curl 'https://127.0.0.1:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-

您可以指定任何数据格式。‘Values’ 格式与编写 INSERT INTO t VALUES 时使用的格式相同

$ echo '(7),(8),(9)' | curl 'https://127.0.0.1:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-

要从制表符分隔的转储中插入数据,请指定相应的格式

$ echo -ne '10\n11\n12\n' | curl 'https://127.0.0.1:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-

读取表内容。由于并行查询处理,数据以随机顺序输出

$ curl 'https://127.0.0.1:8123/?query=SELECT%20a%20FROM%20t'
7
8
9
10
11
12
1
2
3
4
5
6

删除表。

$ echo 'DROP TABLE t' | curl 'https://127.0.0.1:8123/' --data-binary @-

对于不返回数据表的成功请求,将返回一个空的响应主体。

压缩

在传输大量数据或创建立即压缩的转储时,您可以使用压缩来减少网络流量。

在传输数据时,您可以使用 ClickHouse 内部压缩格式。压缩数据具有非标准格式,您需要 clickhouse-compressor 程序才能使用它。它与 clickhouse-client 包一起安装。为了提高数据插入效率,您可以使用 http_native_compression_disable_checksumming_on_decompress 设置禁用服务器端校验和验证。

如果在 URL 中指定 compress=1,服务器将压缩发送给您的数据。如果在 URL 中指定 decompress=1,服务器将解压缩您在 POST 方法中传递的数据。

您还可以选择使用 HTTP 压缩。ClickHouse 支持以下 压缩方法

  • gzip
  • br
  • deflate
  • xz
  • zstd
  • lz4
  • bz2
  • snappy

要发送压缩的 POST 请求,请附加请求标头 Content-Encoding: compression_method。为了使 ClickHouse 压缩响应,请使用 enable_http_compression 设置启用压缩,并将 Accept-Encoding: compression_method 标头附加到请求中。您可以为所有压缩方法在 http_zlib_compression_level 设置中配置数据压缩级别。

信息

某些 HTTP 客户端可能默认情况下会解压缩来自服务器的数据(使用 gzipdeflate),即使您正确使用了压缩设置,您也可能会获得解压缩的数据。

示例

# Sending compressed data to the server
$ echo "SELECT 1" | gzip -c | \
curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'https://127.0.0.1:8123/'
# Receiving compressed data archive from the server
$ curl -vsS "https://127.0.0.1:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3'
$ zcat result.gz
0
1
2
# Receiving compressed data from the server and using the gunzip to receive decompressed data
$ curl -sS "https://127.0.0.1:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 3' | gunzip -
0
1
2

默认数据库

您可以使用 ‘database’ URL 参数或 ‘X-ClickHouse-Database’ 标头指定默认数据库。

$ echo 'SELECT number FROM numbers LIMIT 10' | curl 'https://127.0.0.1:8123/?database=system' --data-binary @-
0
1
2
3
4
5
6
7
8
9

默认情况下,服务器设置中注册的数据库用作默认数据库。默认情况下,这是名为 ‘default’ 的数据库。或者,您始终可以使用表名前面的点指定数据库。

用户名和密码可以通过三种方式之一指示

  1. 使用 HTTP 基本身份验证。示例
$ echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
  1. 在 ‘user’ 和 ‘password’ URL 参数中(我们不建议使用此方法,因为参数可能会被 Web 代理记录并在浏览器中缓存)。示例
$ echo 'SELECT 1' | curl 'https://127.0.0.1:8123/?user=user&password=password' -d @-
  1. 使用 ‘X-ClickHouse-User’ 和 ‘X-ClickHouse-Key’ 标头。示例
$ echo 'SELECT 1' | curl -H 'X-ClickHouse-User: user' -H 'X-ClickHouse-Key: password' 'https://127.0.0.1:8123/' -d @-

如果未指定用户名,则使用 default 名称。如果未指定密码,则使用空密码。您还可以使用 URL 参数为处理单个查询或整个设置配置文件指定任何设置。例如:https://127.0.0.1:8123/?profile=web&max_rows_to_read=1000000000&query=SELECT+1

有关更多信息,请参阅 设置 部分。

$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'https://127.0.0.1:8123/?' --data-binary @-
0
1
2
3
4
5
6
7
8
9

有关其他参数的信息,请参阅“SET”部分。

类似地,您可以在 HTTP 协议中使用 ClickHouse 会话。为此,您需要将 session_id GET 参数添加到请求中。您可以使用任何字符串作为会话 ID。默认情况下,会话在 60 秒不活动后终止。要更改此超时时间,请修改服务器配置中的 default_session_timeout 设置,或将 session_timeout GET 参数添加到请求中。要检查会话状态,请使用 session_check=1 参数。在一个会话中一次只能执行一个查询。

您可以在 X-ClickHouse-Progress 响应标头中接收有关查询进度信息。为此,请启用 send_progress_in_http_headers。标头序列示例

X-ClickHouse-Progress: {"read_rows":"2752512","read_bytes":"240570816","total_rows_to_read":"8880128","elapsed_ns":"662334"}
X-ClickHouse-Progress: {"read_rows":"5439488","read_bytes":"482285394","total_rows_to_read":"8880128","elapsed_ns":"992334"}
X-ClickHouse-Progress: {"read_rows":"8783786","read_bytes":"819092887","total_rows_to_read":"8880128","elapsed_ns":"1232334"}

可能的标头字段

  • read_rows — 已读取的行数。
  • read_bytes — 以字节为单位读取的数据量。
  • total_rows_to_read — 要读取的总行数。
  • written_rows — 已写入的行数。
  • written_bytes — 以字节为单位写入的数据量。

如果 HTTP 连接断开,正在运行的请求不会自动停止。解析和数据格式化在服务器端执行,使用网络可能会效率低下。可选的 ‘query_id’ 参数可以作为查询 ID 传递(任何字符串)。有关更多信息,请参阅“设置,replace_running_query”部分。

可选的 ‘quota_key’ 参数可以作为配额密钥传递(任何字符串)。有关更多信息,请参阅“配额”部分。

HTTP 接口允许传递外部数据(外部临时表)以进行查询。有关更多信息,请参阅“查询处理的外部数据”部分。

响应缓冲

您可以在服务器端启用响应缓冲。为此提供了 buffer_sizewait_end_of_query URL 参数。还可以使用设置 http_response_buffer_sizehttp_wait_end_of_query

buffer_size 决定了在服务器内存中缓冲结果的字节数。如果结果主体大于此阈值,则缓冲区将写入 HTTP 通道,剩余数据将直接发送到 HTTP 通道。

要确保缓冲整个响应,请设置 wait_end_of_query=1。在这种情况下,未存储在内存中的数据将缓存在服务器临时文件中。

示例

$ curl -sS 'https://127.0.0.1:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d 'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'

使用缓冲来避免在将响应代码和 HTTP 标头发送到客户端后发生查询处理错误的情况。在这种情况下,错误消息将写入响应主体的末尾,并且在客户端,错误只能在解析阶段检测到。

使用查询参数设置角色

这是 ClickHouse 24.4 中添加的新功能。

在某些特定场景下,在执行语句本身之前可能需要先设置授予的角色。但是,无法将 SET ROLE 和语句一起发送,因为不允许使用多语句

curl -sS "https://127.0.0.1:8123" --data-binary "SET ROLE my_role;SELECT * FROM my_table;"

这将导致错误

Code: 62. DB::Exception: Syntax error (Multi-statements are not allowed)

为了克服此限制,可以使用 role 查询参数

curl -sS "https://127.0.0.1:8123?role=my_role" --data-binary "SELECT * FROM my_table;"

这等效于在语句之前执行 SET ROLE my_role

此外,可以指定多个 role 查询参数

curl -sS "https://127.0.0.1:8123?role=my_role&role=my_other_role" --data-binary "SELECT * FROM my_table;"

在这种情况下,?role=my_role&role=my_other_role 的作用类似于在语句之前执行 SET ROLE my_role, my_other_role

HTTP 响应代码注意事项

由于 HTTP 协议的限制,HTTP 200 响应代码不能保证查询成功。

这是一个示例

curl -v -Ss "https://127.0.0.1:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)"
* Trying 127.0.0.1:8123...
...
< HTTP/1.1 200 OK
...
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(number, 2) :: 1) -> throwIf(equals(number, 2))

这种行为的原因是 HTTP 协议的特性。HTTP 标头首先发送,HTTP 代码为 200,然后是 HTTP 主体,然后错误作为纯文本注入到主体中。此行为独立于使用的格式,无论是 NativeTSV 还是 JSON;错误消息始终位于响应流的中间。您可以通过启用 wait_end_of_query=1 (响应缓冲) 来缓解此问题。在这种情况下,HTTP 标头的发送将延迟到整个查询解决为止。但是,这并不能完全解决问题,因为结果仍然必须适合 http_response_buffer_size,并且其他设置(如 send_progress_in_http_headers)可能会干扰标头的延迟。唯一捕获所有错误的方法是在使用所需的格式解析 HTTP 主体之前分析它。

带参数的查询

您可以创建一个带参数的查询,并从相应的 HTTP 请求参数传递参数值。有关更多信息,请参阅 CLI 的带参数的查询

示例

$ curl -sS "<address>?param_id=2&param_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"

URL 参数中的制表符

查询参数从“转义”格式解析。这有一些好处,例如能够将空值明确地解析为 \N。这意味着制表符应编码为 \t(或 \ 和一个制表符)。例如,以下内容在 abc123 之间包含一个实际的制表符,输入字符串被拆分为两个值

curl -sS "https://127.0.0.1:8123" -d "SELECT splitByChar('\t', 'abc      123')"
['abc','123']

但是,如果您尝试在 URL 参数中使用 %09 编码实际的制表符,它将无法正确解析

curl -sS "https://127.0.0.1:8123?param_arg1=abc%09123" -d "SELECT splitByChar('\t', {arg1:String})"
Code: 457. DB::Exception: Value abc 123 cannot be parsed as String for query parameter 'arg1' because it isn't parsed completely: only 3 of 7 bytes was parsed: abc. (BAD_QUERY_PARAMETER) (version 23.4.1.869 (official build))

如果使用 URL 参数,则需要将 \t 编码为 %5C%09。例如

curl -sS "https://127.0.0.1:8123?param_arg1=abc%5C%09123" -d "SELECT splitByChar('\t', {arg1:String})"
['abc','123']

预定义的 HTTP 接口

ClickHouse 通过 HTTP 接口支持特定查询。例如,您可以按如下方式将数据写入表

$ echo '(4),(5),(6)' | curl 'https://127.0.0.1:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-

ClickHouse 还支持预定义的 HTTP 接口,这可以帮助您更轻松地与第三方工具(如 Prometheus 导出器)集成。

示例

  • 首先,将此部分添加到服务器配置文件中
<http_handlers>
<rule>
<url>/predefined_query</url>
<methods>POST,GET</methods>
<handler>
<type>predefined_query_handler</type>
<query>SELECT * FROM system.metrics LIMIT 5 FORMAT Template SETTINGS format_template_resultset = 'prometheus_template_output_format_resultset', format_template_row = 'prometheus_template_output_format_row', format_template_rows_between_delimiter = '\n'</query>
</handler>
</rule>
<rule>...</rule>
<rule>...</rule>
</http_handlers>
  • 您现在可以直接请求 URL 以获取 Prometheus 格式的数据
$ curl -v 'https://127.0.0.1:8123/predefined_query'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /predefined_query HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 28 Apr 2020 08:52:56 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< X-ClickHouse-Server-Display-Name: i-mloy5trc
< Transfer-Encoding: chunked
< X-ClickHouse-Query-Id: 96fe0052-01e6-43ce-b12a-6b7370de6e8a
< X-ClickHouse-Format: Template
< X-ClickHouse-Timezone: Asia/Shanghai
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}
<
# HELP "Query" "Number of executing queries"
# TYPE "Query" counter
"Query" 1

# HELP "Merge" "Number of executing background merges"
# TYPE "Merge" counter
"Merge" 0

# HELP "PartMutation" "Number of mutations (ALTER DELETE/UPDATE)"
# TYPE "PartMutation" counter
"PartMutation" 0

# HELP "ReplicatedFetch" "Number of data parts being fetched from replica"
# TYPE "ReplicatedFetch" counter
"ReplicatedFetch" 0

# HELP "ReplicatedSend" "Number of data parts being sent to replicas"
# TYPE "ReplicatedSend" counter
"ReplicatedSend" 0

* Connection #0 to host localhost left intact

* Connection #0 to host localhost left intact

从示例中可以看出,如果在 config.xml 文件中配置了 http_handlers,并且 http_handlers 可以包含许多 rules。ClickHouse 会将接收到的 HTTP 请求与 rule 中的预定义类型进行匹配,并且第一个匹配的规则会运行处理程序。然后,如果匹配成功,ClickHouse 将执行相应的预定义查询。

现在 rule 可以配置 methodheadersurlhandler

  • method 负责匹配 HTTP 请求的方法部分。method 完全符合 HTTP 协议中 方法 的定义。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的方法部分。

  • url 负责匹配 HTTP 请求的 URL 部分。它与 RE2 的正则表达式兼容。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的 URL 部分。

  • headers 负责匹配 HTTP 请求的标头部分。它与 RE2 的正则表达式兼容。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的标头部分。

  • handler 包含主要处理部分。现在 handler 可以配置 typestatuscontent_typehttp_response_headersresponse_contentqueryquery_param_nametype 目前支持三种类型:predefined_query_handlerdynamic_query_handlerstatic

    • query — 与 predefined_query_handler 类型一起使用,在调用处理程序时执行查询。

    • query_param_name — 与 dynamic_query_handler 类型一起使用,提取并执行 HTTP 请求参数中与 query_param_name 值对应的值。

    • status — 与 static 类型一起使用,响应状态码。

    • content_type — 与任何类型一起使用,响应 content-type

    • http_response_headers — 与任何类型一起使用,响应标头映射。也可以用来设置内容类型。

    • response_content — 与 static 类型一起使用,发送到客户端的响应内容,当使用前缀“file://”或“config://”时,从文件或配置中查找发送到客户端的内容。

以下是不同 type 的配置方法。

predefined_query_handler

predefined_query_handler 支持设置 Settingsquery_params 值。您可以在 predefined_query_handler 类型中配置 query

query 值是 predefined_query_handler 的预定义查询,当匹配 HTTP 请求时由 ClickHouse 执行,并返回查询结果。这是一个必须的配置。

以下示例定义了 max_threadsmax_final_threads 设置的值,然后查询系统表以检查这些设置是否已成功设置。

注意

要保留默认的 handlers(如 queryplayping),请添加 <defaults/> 规则。

示例

<http_handlers>
<rule>
<url><![CDATA[regex:/query_param_with_url/(?P<name_1>[^/]+)]]></url>
<methods>GET</methods>
<headers>
<XXX>TEST_HEADER_VALUE</XXX>
<PARAMS_XXX><![CDATA[regex:(?P<name_2>[^/]+)]]></PARAMS_XXX>
</headers>
<handler>
<type>predefined_query_handler</type>
<query>
SELECT name, value FROM system.settings
WHERE name IN ({name_1:String}, {name_2:String})
</query>
</handler>
</rule>
<defaults/>
</http_handlers>
$ curl -H 'XXX:TEST_HEADER_VALUE' -H 'PARAMS_XXX:max_final_threads' 'https://127.0.0.1:8123/query_param_with_url/max_threads?max_threads=1&max_final_threads=2'
max_final_threads 2
max_threads 1
注意

在一个 predefined_query_handler 中只支持一个 query

dynamic_query_handler

dynamic_query_handler 中,查询以 HTTP 请求的参数形式编写。不同之处在于,在 predefined_query_handler 中,查询是在配置文件中编写的。您可以在 dynamic_query_handler 中配置 query_param_name

ClickHouse 提取并执行 HTTP 请求 URL 中与 query_param_name 值对应的值。query_param_name 的默认值为 /query。这是一个可选配置。如果配置文件中没有定义,则不会传递参数。

为了试验此功能,示例定义了 max_threadsmax_final_threads 以及 queries 的值,以检查设置是否已成功设置。

示例

<http_handlers>
<rule>
<headers>
<XXX>TEST_HEADER_VALUE_DYNAMIC</XXX> </headers>
<handler>
<type>dynamic_query_handler</type>
<query_param_name>query_param</query_param_name>
</handler>
</rule>
<defaults/>
</http_handlers>
$ curl  -H 'XXX:TEST_HEADER_VALUE_DYNAMIC'  'https://127.0.0.1:8123/own?max_threads=1&max_final_threads=2&param_name_1=max_threads&param_name_2=max_final_threads&query_param=SELECT%20name,value%20FROM%20system.settings%20where%20name%20=%20%7Bname_1:String%7D%20OR%20name%20=%20%7Bname_2:String%7D'
max_threads 1
max_final_threads 2

static

static 可以返回 content_typestatusresponse_contentresponse_content 可以返回指定的内容。

示例

返回一条消息。

<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/hi</url>
<handler>
<type>static</type>
<status>402</status>
<content_type>text/html; charset=UTF-8</content_type>
<http_response_headers>
<Content-Language>en</Content-Language>
<X-My-Custom-Header>43</X-My-Custom-Header>
</http_response_headers>
<response_content>Say Hi!</response_content>
</handler>
</rule>
<defaults/>
</http_handlers>

http_response_headers 可用于设置内容类型,而不是 content_type

<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/hi</url>
<handler>
<type>static</type>
<status>402</status>
<http_response_headers>
<Content-Type>text/html; charset=UTF-8</Content-Type>
<Content-Language>en</Content-Language>
<X-My-Custom-Header>43</X-My-Custom-Header>
</http_response_headers>
<response_content>Say Hi!</response_content>
</handler>
</rule>
<defaults/>
</http_handlers>
$ curl -vv  -H 'XXX:xxx' 'https://127.0.0.1:8123/hi'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /hi HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 402 Payment Required
< Date: Wed, 29 Apr 2020 03:51:26 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}
<
* Connection #0 to host localhost left intact
Say Hi!%

从配置中查找发送到客户端的内容。

<get_config_static_handler><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></get_config_static_handler>

<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_config_static_handler</url>
<handler>
<type>static</type>
<response_content>config://get_config_static_handler</response_content>
</handler>
</rule>
</http_handlers>
$ curl -v  -H 'XXX:xxx' 'https://127.0.0.1:8123/get_config_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_config_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:01:24 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}
<
* Connection #0 to host localhost left intact
<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>%

从文件中查找发送到客户端的内容。

<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_absolute_path_static_handler</url>
<handler>
<type>static</type>
<content_type>text/html; charset=UTF-8</content_type>
<http_response_headers>
<ETag>737060cd8c284d8af7ad3082f209582d</ETag>
</http_response_headers>
<response_content>file:///absolute_path_file.html</response_content>
</handler>
</rule>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_relative_path_static_handler</url>
<handler>
<type>static</type>
<content_type>text/html; charset=UTF-8</content_type>
<http_response_headers>
<ETag>737060cd8c284d8af7ad3082f209582d</ETag>
</http_response_headers>
<response_content>file://./relative_path_file.html</response_content>
</handler>
</rule>
</http_handlers>
$ user_files_path='/var/lib/clickhouse/user_files'
$ sudo echo "<html><body>Relative Path File</body></html>" > $user_files_path/relative_path_file.html
$ sudo echo "<html><body>Absolute Path File</body></html>" > $user_files_path/absolute_path_file.html
$ curl -vv -H 'XXX:xxx' 'https://127.0.0.1:8123/get_absolute_path_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_absolute_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:16 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}
<
<html><body>Absolute Path File</body></html>
* Connection #0 to host localhost left intact
$ curl -vv -H 'XXX:xxx' 'https://127.0.0.1:8123/get_relative_path_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_relative_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:31 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334"}
<
<html><body>Relative Path File</body></html>
* Connection #0 to host localhost left intact

HTTP 流式传输期间异常时的有效 JSON/XML 响应 {valid-output-on-exception-http-streaming}

在通过 HTTP 执行查询时,当部分数据已发送时可能会发生异常。通常,即使使用某些特定数据格式输出数据,异常也会以纯文本形式发送到客户端,并且输出在指定数据格式方面可能会变得无效。为了防止这种情况,您可以使用设置 http_write_exception_in_output_format(默认启用),它将告诉 ClickHouse 以指定的格式写入异常(目前支持 XML 和 JSON* 格式)。

示例

$ curl 'https://127.0.0.1:8123/?query=SELECT+number,+throwIf(number>3)+from+system.numbers+format+JSON+settings+max_block_size=1&http_write_exception_in_output_format=1'
{
"meta":
[
{
"name": "number",
"type": "UInt64"
},
{
"name": "throwIf(greater(number, 2))",
"type": "UInt8"
}
],

"data":
[
{
"number": "0",
"throwIf(greater(number, 2))": 0
},
{
"number": "1",
"throwIf(greater(number, 2))": 0
},
{
"number": "2",
"throwIf(greater(number, 2))": 0
}
],

"rows": 3,

"exception": "Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)"
}
$ curl 'https://127.0.0.1:8123/?query=SELECT+number,+throwIf(number>2)+from+system.numbers+format+XML+settings+max_block_size=1&http_write_exception_in_output_format=1'
<?xml version='1.0' encoding='UTF-8' ?>
<result>
<meta>
<columns>
<column>
<name>number</name>
<type>UInt64</type>
</column>
<column>
<name>throwIf(greater(number, 2))</name>
<type>UInt8</type>
</column>
</columns>
</meta>
<data>
<row>
<number>0</number>
<field>0</field>
</row>
<row>
<number>1</number>
<field>0</field>
</row>
<row>
<number>2</number>
<field>0</field>
</row>
</data>
<rows>3</rows>
<exception>Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)</exception>
</result>