Liquid 模板引擎深度集成——Huginn 的数据转换管道
Liquid 模板引擎深度集成——Huginn 的数据转换管道
学习目标
- 理解 Huginn 中 Liquid 模板的三层扩展(过滤器、标签、块)
- 掌握 Agent 配置的递归插值机制
- 学会使用自定义过滤器处理 URI、正则、JSON 和加密
- 了解安全上下文栈的设计与凭据访问
前置知识
本章涉及 Liquid 模板引擎的通用原理,建议先阅读:
下文假设你已理解 Liquid 的基础语法和扩展机制,直接聚焦 Huginn 的具体实现。
项目实践
Agent 配置的全模板化
在 Huginn 中,Agent 的 options 字段的所有字符串值都支持 Liquid 插值:
这意味着用户可以在 Agent 配置的任何字符串位置使用模板变量:
{ "url": "https://api.weather.com/{{ city }}/current", "headers": { "Authorization": "Bearer {{ api_key }}" }, "extract": { "temp": { "path": "current.temperature" } }}自定义过滤器分类
Huginn 注册了大量自定义 Liquid 过滤器:
URI 操作类
| 过滤器 | 功能 | 示例 |
|---|---|---|
uri_escape | RFC 3986 URL 编码 | `{{ query |
to_uri | 解析 URI 对象,可选合并 base URI | `{{ path |
uri_expand | 递归跟随 HTTP 重定向(最多 5 次) | `{{ short_url |
rebase_hrefs | 重写 HTML 中的相对链接 | `{{ html |
数据处理类
| 过滤器 | 功能 | 示例 |
|---|---|---|
json | 序列化为 JSON 字符串 | `{{ data |
fromjson | 解析 JSON 字符串 | `{{ json_str |
hex_encode / hex_decode | 十六进制编码/解码 | `{{ data |
as_object | 返回原始 Ruby 对象(非字符串) | `{{ data |
正则处理类
| 过滤器 | 功能 | 示例 |
|---|---|---|
regex_extract | 正则提取(支持捕获组索引) | `{{ text |
regex_replace | 正则全局替换 | `{{ text |
regex_replace_first | 正则首次匹配替换 | `{{ text |
加密哈希类
| 过滤器 | 功能 | 示例 |
|---|---|---|
md5 | MD5 哈希 | `{{ text |
sha1 / sha256 | SHA 哈希 | `{{ text |
hmac_sha1 / hmac_sha256 | HMAC 签名 | `{{ data |
自定义标签
| 标签 | 功能 | 示例 |
|---|---|---|
credential | 安全访问用户凭据 | {% credential api_key %} |
uuidv4 | 生成 UUID | {% uuidv4 %} |
line_break | 插入换行符 | {% line_break %} |
自定义块:正则替换
Huginn 扩展了两个正则替换块,支持在替换文本中使用匹配变量:
{% regex_replace "\w+" in %}Use me like this.{% with %}{{ match | capitalize }}{% endregex_replace %}结果:Use Me Like This.
上下文栈系统
关键设计:
_agent_始终可用——在模板中引用{{ _agent_.name }}或{{ _agent_.id }}- 通过 Controller 关系自动注入 KeyValueStore 数据——不需要手动配置
interpolate_with(event)动态推送事件 payload 到作用域顶部interpolate_with('target' => target)用于 CommanderAgent 中引用目标 Agent
问题与规避
as_object 位置错误
as_object 必须作为最后一个过滤器使用,否则后续的字符串过滤器会报错。
错误写法:{{ data | as_object | upcase }}(as_object 后不是字符串)
正确写法:{{ data | upcase | as_object }}
凭据标签的作用域
{% credential api_key %} 只能访问当前用户的凭据,不能跨用户访问。
安全保证:凭据标签内部通过 user.user_credentials.where(credential_name: name) 查询,天然隔离。
模板验证延迟
模板错误在保存时通过 validate_interpolation 检查,但某些动态上下文下的错误只能在运行时暴露。
规避方式:使用 Dry Run 功能在实际运行前测试模板。
设计取舍
全文插值 vs 限定插值
| 维度 | 全文插值(Huginn) | 限定插值(特定字段) |
|---|---|---|
| 灵活性 | 极高(任何配置都可模板化) | 低(只有指定字段支持) |
| 安全性 | 需要完整的沙箱 | 较低风险 |
| 性能 | 递归解析开销 | 仅解析指定字段 |
| 用户体验 | 一致(所有字段行为相同) | 不一致(某些字段支持,某些不支持) |
Huginn 选择全文插值,因为 Liquid 的安全沙箱保证了即使任何配置值都可模板化,也不会执行恶意代码。
参考来源
- Liquid Template Language — Liquid 官方文档
- RFC 3986 — URI 编码标准