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
。
在健康检查脚本中使用 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 客户端可能默认情况下会解压缩来自服务器的数据(使用 gzip
和 deflate
),即使您正确使用了压缩设置,您也可能会获得解压缩的数据。
示例
# 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’ 的数据库。或者,您始终可以使用表名前面的点指定数据库。
用户名和密码可以通过三种方式之一指示
- 使用 HTTP 基本身份验证。示例
$ echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
- 在 ‘user’ 和 ‘password’ URL 参数中(我们不建议使用此方法,因为参数可能会被 Web 代理记录并在浏览器中缓存)。示例
$ echo 'SELECT 1' | curl 'https://127.0.0.1:8123/?user=user&password=password' -d @-
- 使用 ‘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_size
和 wait_end_of_query
URL 参数。还可以使用设置 http_response_buffer_size
和 http_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 主体,然后错误作为纯文本注入到主体中。此行为独立于使用的格式,无论是 Native
、TSV
还是 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¶m_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"
URL 参数中的制表符
查询参数从“转义”格式解析。这有一些好处,例如能够将空值明确地解析为 \N
。这意味着制表符应编码为 \t
(或 \
和一个制表符)。例如,以下内容在 abc
和 123
之间包含一个实际的制表符,输入字符串被拆分为两个值
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
可以配置 method
、headers
、url
、handler
method
负责匹配 HTTP 请求的方法部分。method
完全符合 HTTP 协议中 方法 的定义。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的方法部分。url
负责匹配 HTTP 请求的 URL 部分。它与 RE2 的正则表达式兼容。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的 URL 部分。headers
负责匹配 HTTP 请求的标头部分。它与 RE2 的正则表达式兼容。这是一个可选配置。如果在配置文件中未定义,则它不匹配 HTTP 请求的标头部分。handler
包含主要处理部分。现在handler
可以配置type
、status
、content_type
、http_response_headers
、response_content
、query
、query_param_name
。type
目前支持三种类型:predefined_query_handler、dynamic_query_handler、static。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
支持设置 Settings
和 query_params
值。您可以在 predefined_query_handler
类型中配置 query
。
query
值是 predefined_query_handler
的预定义查询,当匹配 HTTP 请求时由 ClickHouse 执行,并返回查询结果。这是一个必须的配置。
以下示例定义了 max_threads 和 max_final_threads
设置的值,然后查询系统表以检查这些设置是否已成功设置。
要保留默认的 handlers
(如 query
、play
、ping
),请添加 <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_threads 和 max_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¶m_name_1=max_threads¶m_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_type、status 和 response_content
。response_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>