StarRocks http_request 函数详解:在 SQL 中发起 HTTP 请求的完整实战指南
【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks
导读
StarRocks 的http_request标量函数允许你在纯 SQL 语句中直接发起 HTTP/HTTPS 请求,并将响应以 JSON 字符串形式返回,从而在查询层面无缝对接外部 REST API、Webhook、监控告警等场景。本文以 docs/en/sql-reference/sql-functions/scalar-functions/http_request.md 为骨架,结合 BE 端函数实现与 FE 端安全配置源码,系统讲解其语法、参数、返回值格式、安全机制与实战用法,帮助你安全、高效地在 StarRocks 中调用外部 HTTP 服务。
一、函数能力概述与适用场景
http_request是一个执行 HTTP 请求并返回 JSON 字符串的标量函数,支持命名参数与位置参数两种调用方式。它把“外部 API 调用”变成了一种可在 SQL 中组合、可被SELECT、WHERE、JOIN等标准 SQL 结构灵活使用的表达式能力。
典型应用场景包括:
- 在报表生成后调用企业 IM(如 Slack)的 Webhook 推送通知;
- 在查询中将外部 REST API 返回的数据与本地表数据关联;
- 在 ETL 流程中直接调用第三方服务做数据增强或校验;
- 将 StarRocks 作为轻量级调度/编排层,在 SQL 任务中触发外部系统动作。
从实现角度看,该函数由 BE 端 http_request_functions.cpp 提供向量化执行实现,底层基于HttpClient(封装 libcurl)发起请求,并在 FE 端注册于 FunctionSet.java(HTTP_REQUEST = "http_request"),其安全策略由 FE 的全局配置下发至 BE 执行。
内置限制(Limits)
在使用前必须先了解该函数的内置硬性限制:
| 限制项 | 值 |
|---|---|
| 最大响应体大小 | 1 MB |
| 最大重定向次数 | 20 次 |
| 最小超时时间 | 1 ms |
| 最大超时时间 | 300,000 ms(5 分钟) |
| 支持的协议 | 仅 HTTP、HTTPS |
源码中DEFAULT_MAX_RESPONSE_SIZE = 1048576(即 1 MB)定义了响应体上限,BE 端通过流式回调在下载过程中实时累计大小,一旦超过即中止下载并返回错误(见 http_request_functions.cpp)。
二、语法与参数详解
2.1 语法
-- 命名参数(推荐) http_request( url => <url>, [method => <method>,] [body => <body>,] [headers => <headers>,] [timeout_ms => <timeout_ms>,] [ssl_verify => <ssl_verify>,] [username => <username>,] [password => <password>] ) -- 位置参数 http_request(<url>[, <method>[, <body>[, <headers>[, <timeout_ms>[, <ssl_verify>[, <username>[, <password>]]]]]]])命名参数可任意调整顺序,代码可读性更高;位置参数则必须严格按照上述顺序填写,且跳过中间参数时仍需用占位值补齐。
2.2 参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
url | VARCHAR | 是 | - | 目标 URL,必须是 HTTP 或 HTTPS。 |
method | VARCHAR | 否 | 'GET' | HTTP 方法:GET、POST、PUT、DELETE、HEAD、OPTIONS。 |
body | VARCHAR | 否 | '' | 请求体内容。 |
headers | VARCHAR | 否 | '{}' | 自定义请求头,以 JSON 对象字符串形式传入。 |
timeout_ms | INT | 否 | 30000 | 请求超时时间(毫秒),取值范围 1 ~ 300,000。 |
ssl_verify | BOOLEAN | 否 | true | 是否校验 SSL 证书。 |
username | VARCHAR | 否 | '' | HTTP Basic Authentication 用户名。 |
password | VARCHAR | 否 | '' | HTTP Basic Authentication 密码。 |
2.3 参数行为细节(源码视角)
从 BE 端实现(http_request_functions.cpp)可以确认以下细节:
- method 大小写不敏感:实现会将方法名统一转为大写后与
GET/POST/PUT/DELETE/HEAD/OPTIONS匹配,非法方法直接返回错误(Invalid HTTP method '...'),而不是静默回退到 GET(parse_http_method)。 - timeout 自动钳位:超出
[1, 300000]的值会被自动裁剪到边界值(超时处理)。 - headers 必须是 JSON 对象:
headers参数使用 simdjson 解析,必须形如{"Content-Type": "application/json"};非 JSON 对象会返回Invalid headers JSON format错误(parse_headers_json)。 - body 仅对可携带请求体的方法生效:源码中仅当方法为
POST、PUT、DELETE时才设置 payload。 - url 为 NULL 时整行返回 NULL:向量化实现中逐行处理,URL 为 NULL 的行直接追加 NULL(逐行处理逻辑),
RETURN_IF_COLUMNS_ONLY_NULL会在整列全为 NULL 时短路返回。
三、返回值格式
函数返回 VARCHAR 类型,内容是一个 JSON 对象。
成功响应:
{"status": <http_code>, "body": <response_content>}错误响应:
{"status": -1, "body": null, "error": "<error_message>"}这里有一个值得注意的实现细节:body字段的编码方式是智能的——如果响应体本身是合法 JSON,则直接内嵌而不转义;否则将其作为 JSON 字符串转义输出;若响应体包含非法 UTF-8 编码,则返回错误(build_json_response)。这意味着你可以直接对成功响应用json_query继续解析,也可以嵌套解析 body 中的 JSON 内容。
四、实战示例
以下示例均来自官方文档,并可直接在 StarRocks 中执行验证。
4.1 简单 GET 请求
SELECT http_request(url => 'https://httpbin.org/get');4.2 用 json_query 提取状态码
SELECT json_query( http_request(url => 'https://httpbin.org/get'), '$.status' ) AS status_code;4.3 POST 请求携带 JSON body
SELECT http_request( url => 'https://httpbin.org/post', method => 'POST', headers => '{"Content-Type": "application/json"}', body => '{"name": "StarRocks", "type": "database"}' );4.4 自定义请求头
SELECT http_request( url => 'https://api.example.com/data', headers => '{"Authorization": "Bearer token123", "Accept": "application/json"}' );4.5 HTTP Basic 认证
SELECT http_request( url => 'https://httpbin.org/basic-auth/user/passwd', username => 'user', password => 'passwd' );4.6 自定义超时
SELECT http_request( url => 'https://slow-api.example.com/data', timeout_ms => 60000 );4.7 命名参数任意顺序
SELECT http_request( method => 'POST', timeout_ms => 5000, url => 'https://httpbin.org/post', body => '{"key": "value"}' );4.8 位置参数
SELECT http_request('https://httpbin.org/post', 'POST', '{"key": "value"}');4.9 发送 Slack Webhook 通知
SELECT http_request( url => 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL', method => 'POST', headers => '{"Content-Type": "application/json"}', body => '{"text": "Alert: Daily report generated from StarRocks!"}' );4.10 解析嵌套 JSON 响应
SELECT json_query( json_query( http_request(url => 'https://jsonplaceholder.typicode.com/posts/1'), '$.body' ), '$.title' ) AS post_title;4.11 关闭 SSL 校验(受管理员策略约束)
SELECT http_request( url => 'https://self-signed.example.com/api', ssl_verify => false );注意:如果管理员已将 FE 配置
http_request_ssl_verification_required设为true,则该选项会被忽略。此时若用户显式传ssl_verify => false,BE 端会直接返回错误SSL verification is enforced by administrator...(见 http_request_functions.cpp)。
五、安全机制:内置 SSRF 防护
由于http_request允许任意 SQL 用户发起出站 HTTP 请求,StarRocks 为该函数内置了完整的SSRF(服务端请求伪造)防护,包含:
- DNS 重绑定防护(DNS pinning):在请求执行前先解析域名并校验解析出的 IP,随后通过 libcurl 的
CURLOPT_RESOLVE将域名“钉死”在已校验的 IP 上再发起请求,校验与连接使用同一份解析结果,从根本上消除 TOCTOU(检查时间与使用时间不一致)漏洞窗口(validate_host_security 与 DNS pinning)。 - 重定向限制:自动重定向被禁用(
set_follow_redirects(false)),避免请求被重定向到内网地址而绕过校验(重定向禁用)。文档中同时说明最大重定向次数为 20 次。 - 私网与链路本地地址拦截:默认拦截 RFC1918 私网地址、回环地址及链路本地地址(含云元数据服务地址
169.254.0.0/16),并对链路本地地址给出专门的告警信息(私网 IP 拦截)。
5.1 安全级别
| 级别 | 名称 | 说明 |
|---|---|---|
| 1 | TRUSTED | 允许所有请求,包括私网 IP。 |
| 2 | PUBLIC | 拦截私网 IP,允许所有公网主机。 |
| 3 | RESTRICTED | 所有主机都必须命中白名单。(默认) |
| 4 | PARANOID | 拦截所有请求。 |
安全级别在 BE 端以枚举HttpSecurityLevel定义(http_request_functions.h),对应测试用例覆盖了各级别行为,例如securityLevel1AllowsEverythingTest、securityLevel2PublicOpenPrivateNeedsAllowlistTest、securityLevel3RequiresAllowlistTest、securityLevel4BlocksAllRequestsTest等(见 http_request_functions_test.cpp)。
5.2 配置项
以下配置均为 FE 端动态配置(@ConfField(mutable = true)),定义于 Config.java,可通过ADMIN SET FRONTEND CONFIG在线修改,并通过会话变量(见 SessionVariable.java)经 Thrift 下发到 BE 执行端:
| 配置 | 类型 | 默认值 | 说明 |
|---|---|---|---|
http_request_security_level | INT | 3 | 安全级别(1-4)。 |
http_request_host_allowlist_regexp | VARCHAR | '' | 允许的主机名正则表达式(支持逗号分隔多个模式)。 |
http_request_ip_allowlist | VARCHAR | '' | 允许的 IPv4 地址列表,逗号分隔。 |
http_request_allow_private_in_allowlist | BOOLEAN | false | 若命中白名单,是否允许私网 IP。 |
http_request_ssl_verification_required | BOOLEAN | true | 强制 SSL 校验(用户无法自行关闭)。 |
5.3 配置示例
ADMIN SET FRONTEND CONFIG ("http_request_security_level" = "3"); ADMIN SET FRONTEND CONFIG ("http_request_host_allowlist_regexp" = "api\\.example\\.com|.*\\.trusted\\.org"); ADMIN SET FRONTEND CONFIG ("http_request_ip_allowlist" = "203.0.113.1,198.51.100.0");5.4 白名单行为矩阵
| 目标 | 级别 2(PUBLIC) | 级别 3(RESTRICTED) |
|---|---|---|
| 公网 IP(不在白名单) | 允许 | 拦截 |
| 公网 IP(在白名单) | 允许 | 允许 |
| 私网 IP(不在白名单) | 拦截 | 拦截 |
私网 IP(在白名单 +allow_private=true) | 允许 | 允许 |
5.5 拦截的 IP 段(级别 2-4)
127.0.0.0/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16、0.0.0.0/8,以及 IPv6 回环地址(::1)、链路本地地址(fe80::/10)、唯一本地地址(fc00::/7)。
5.6 白名单判断实现要点
从 check_allowlist 的实现可见,命中判断是**“IP 精确匹配 OR 主机正则匹配”**的或关系:
- IP 白名单为精确字符串匹配(check_ip_allowlist);
- 主机白名单为正则匹配(
std::regex_match,需完整匹配而非子串匹配),支持逗号分隔多个正则,非法正则会被跳过并记录 WARNING(init_security_state); - 私网判断会同时识别普通私网地址与链路本地地址,其中链路本地地址(常见于云元数据服务)即使命中白名单也会给出强警告(私网 IP 处理)。
六、最佳实践与注意事项
- 优先使用命名参数:当需要传入多个可选参数时,命名参数可读性更强,且不依赖参数顺序,减少因占位符错位导致的低级错误。
- 注意 1 MB 响应体上限:若目标接口可能返回较大数据,请先在上游做好分页或字段裁剪,避免请求被中止。
- SSRF 策略分级落地:生产环境建议保持默认的
RESTRICTED(级别 3),仅将确需访问的外部域名或 IP 加入白名单;只有在完全可信的封闭网络内才考虑降级到PUBLIC或TRUSTED。级别 4(PARANOID)适合在审计或特殊合规窗口期临时启用。 - 不要轻易关闭 SSL 校验:
http_request_ssl_verification_required默认开启且由管理员强制,这是防止中间人攻击的重要防线;仅对自签名证书的内部服务且已充分评估风险时,才通过ssl_verify => false按调用点关闭。 - 超时设置要合理:默认 30 秒足以覆盖多数场景;对于慢接口可放大到分钟级,但最大不超过 300,000 ms。
- 结合
json_query链式解析:返回值是标准 JSON,可直接嵌套json_query逐层提取字段,将外部 API 数据无缝融入 SQL 表达式。 - 排查问题先看
error字段:请求失败时返回{"status": -1, "body": null, "error": "<error_message>"},其中的错误信息来自 BE 端 libcurl 或安全校验逻辑,是定位 DNS、TLS、超时、白名单等问题的第一手线索。
七、相关资源
- 官方函数文档:http_request.md
- BE 端函数实现:http_request_functions.cpp、http_request_functions.h
- BE 端单元测试:http_request_functions_test.cpp
- FE 端配置定义:Config.java
- FE 端配置下发:SessionVariable.java
- FE 端函数注册:FunctionSet.java
【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考