网关路由
介绍插件如何在网关上注册 HTTP 端点,以及这些路由所遵循的认证、作用域、替换和准入规则。属于插件架构内部机制指南的一部分。
网关 HTTP 路由¶
插件可以通过 api.registerHttpRoute(...) 暴露 HTTP 端点。
api.registerHttpRoute({
path: "/acme/webhook",
auth: "plugin",
match: "exact",
handler: async (_req, res) => {
res.statusCode = 200;
res.end("ok");
return true;
},
});
路由字段:
path:网关 HTTP 服务器下的路由路径。auth:必填,"gateway"或"plugin"。使用"gateway"要求正常的网关认证,或使用"plugin"进行插件管理的认证/webhook 校验。match:可选。"exact"(默认)或"prefix"。handleUpgrade:可选,用于处理同一路由上的 WebSocket 升级请求的处理器。replaceExisting:可选。仅动态生命周期注册在替换自身已有路由时需要。handler:当路由处理了请求时返回true。
注意:
api.registerHttpHandler(...)已被移除,使用会导致插件加载错误。请改用api.registerHttpRoute(...)。- 插件路由必须显式声明
auth。 - 规范等价路径且
match模式相同时共享同一条路由。同一插件发起的静态api.registerHttpRoute(...)调用会替换该路由;其他插件不能替换它。 - 不同
auth级别的重叠路由会被拒绝。exact/prefix回退链只能保持在相同的auth级别上。 - 使用
openclaw/plugin-sdk/webhook-ingress中的registerPluginHttpRoute(...)的动态生命周期代码必须设置replaceExisting: true以刷新自身的规范路由。命名注册只能替换具有相同非空pluginId的路由;当任一方设置了路由source时,双方必须设置相同的非空 source。对于随 SDK 提供的调用方,同一插件的无 source 到无 source 刷新以及匿名到匿名刷新仍然受支持,但命名路由和匿名路由不能互相替换。 - 设置
reuseExistingSameOwner: true可与相同的非空pluginId和source共享规范路由。动态创建的路由会一直保留,直到其最后一个持有者释放它;复用静态api.registerHttpRoute(...)路由则将其生命周期交由插件注册表管理。 - 频道生命周期回调使用其网关的路由注册表。启动路由在其任务完成或恢复流程放弃该任务时过期;
stopAccount路由在停止尝试完成或超时时过期。恢复流程会在替换启动之前撤销被放弃的任务路由,即使启动失败也是如此。已过期的回调不能动态注册或替换路由。 - 将路由
source视为同一插件内稳定的子所有者标识,而不是诊断标签。现有的无 source 调用方可以继续省略它;感知 source 的调用方在刷新时必须保持其不变。 - 动态生命周期注册在被拒绝时默认会记录日志并返回一个空操作的注销回调。当就绪状态依赖于该路由时,设置
throwOnFailure: true;必需的捆绑 webhook 传输使用严格注册,因此没有实时入口就无法报告就绪。 auth: "plugin"路由不会自动获得操作员运行时作用域。它们用于插件管理的 webhook/签名校验,而非特权网关辅助调用。auth: "gateway"路由在网关请求运行时作用域内运行。默认表面(gatewayRuntimeScopeSurface: "write-default")刻意保持保守:- 共享密钥 Bearer 认证(
gateway.auth.mode = "token"/"password")以及任何非 trusted-proxy 认证方法都只会获得单个operator.write作用域,即使调用方发送了x-openclaw-scopes - 没有显式
x-openclaw-scopes请求头的trusted-proxy调用方也保持仅operator.write的旧有表面 - 发送了
x-openclaw-scopes的trusted-proxy调用方则会获得声明的作用域 - 路由可以选择加入
gatewayRuntimeScopeSurface: "trusted-operator",以便在具有身份标识的认证模式下始终遵从x-openclaw-scopes(当请求头缺失时回退到完整的 CLI 默认作用域集合) - 由
auth: "gateway"路由支撑的沙箱化外部 Control UI 标签页使用仅由经过认证的引导签发的短期签名 cookie 授权;plugin-auth 标签页保留其直接 iframe 路径。在挂载之前,父级会在同一个不透明沙箱内运行由路由拥有的探测,并在浏览器隐私策略阻止 cookie 时按失败关闭(fail-closed)处理。该授权绑定到所属插件、匹配的路由根路径和当前认证代数;其进程随机生成的 cookie 名称可防止受信任的同主机网关互相覆盖,但 cookie 从不隔离 TCP 端口。因此,网关主机名构成一个凭据边界:不要在该主机名上共同托管互不信任的服务,包括其他端口。路由分发会拒绝针对由另一插件拥有的嵌套路由的复用。由于沙箱后代在 cookie 意义上属于跨站,该授权仅接受带operator.read的GET和HEAD;变更操作和 WebSocket 升级仍保留在显式经网关认证的表面上。该 cookie 有意不使用 CHIPS:当前浏览器在分区键中包含跨站祖先位,因此嵌套的不透明沙箱框架将失去对同路由资源的访问。该 cookie 需要安全上下文以及浏览器对跨站 cookie 的许可,因此在纯 HTTP 局域网源或完全阻止第三方 cookie 的情况下,gateway-auth 外部标签页不可用;请使用 HTTPS/Tailscale Serve 或采用兼容 cookie 策略的浏览器可信回环。 - 该授权防止网关 Bearer 令牌泄露以及意外的路由/作用域复用;它不会在原生插件之间建立安全边界。原生插件代码及其提供的 UI 内容仍然属于同一个受信任的进程内插件边界的一部分。
- 实用规则:不要假设 gateway-auth 插件路由是隐式的管理员表面。如果你的路由需要仅管理员行为,请选择加入
trusted-operator作用域表面,要求使用具有身份标识的认证模式,并记录显式的x-openclaw-scopes请求头契约。 - 启动插件在网关开始监听后使用其完整运行时注册 HTTP 路由。在启动 sidecar 就绪之前,未被认领的 HTTP 请求会返回
503并附带Retry-After: 1;核心路由继续正常分发。在运行时注册表能够识别路由所有者之前,此通用回退机制覆盖插件路由。 - 在路由匹配和认证之后,普通处理器参与网关根工作准入。已准备就绪或正在重启的网关会在调用处理器之前返回
503。唯一的例外是:由 manifest 授权的auth: "gateway"路由同时选择加入路由特定的trusted-operator表面;它保持可达,以免暂停控制分发无法送达,而同一插件中的普通兄弟路由仍留在准入边界之后。WebSockethandleUpgrade的所有权使用相同的原子准入边界;一旦处理器接受了套接字,该套接字后续的生命周期归插件所有,不再受此边界跟踪。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw