跳到正文

脚本运行限制与配置

本章讲脚本引擎的环境变量、限制与安全、脚本测试入口。API 参考见 脚本 API 参考,入门见 写第一个脚本变换

脚本相关环境变量

变量默认值作用
SCRIPT_MAX_OPERATIONS2000每次脚本执行的最大操作数
SCRIPT_MEMORY_LIMIT_MB64解释器堆上限(MB)
SCRIPT_LAZY_BODYtrue是否对请求/响应体做懒投影;false 走旧整段物化分支

这三个控制操作数上限与内存;其他资源限制(字符串大小、数组元素、栈大小等)由沙箱硬编码,不可配置。改完环境变量需重启容器生效。完整环境变量见 环境变量配置参考

资源限制

限制可配置
最大操作数2,000SCRIPT_MAX_OPERATIONS
解释器堆上限64 MBSCRIPT_MEMORY_LIMIT_MB(运行时创建期约束,变更需重启)
body 懒投影开启SCRIPT_LAZY_BODY(默认 truefalse 走旧整段物化分支,回滚靠显式切回;变更需重启)
最大字符串10 MB固定
最大数组/对象元素10,000固定
正则缓存256 条,5 分钟 TTL固定
栈大小1024 帧固定

ℹ️ body 视图语义SCRIPT_LAZY_BODY=true 时,body 是按需取件的懒投影视图,整份 body 不整段进 JS 堆,JS 堆占用只与脚本访问的字段挂钩。视图在 Array.isArray / instanceof / typeof / Object.keys / 解构 / 展开 / JSON.stringify / 数组方法等标准判断下与真对象一致。已知边界body.x === body.x 为假(不缓存壳),依赖同路径引用相等的脚本须改用值比较。

沙箱限制

脚本可以做什么

  • 读取和修改 body
  • 读取 context 元数据
  • 使用所有内置函数(json_path、str_、regex_、array_* 等)
  • 定义辅助函数
  • 使用标准 JavaScript(循环、条件、闭包、解构等)

脚本不能做什么

被禁止原因
console.log / print防止信息泄露
文件 I/O无文件系统访问
网络 / fetch无网络访问
import / require不能加载外部代码
eval / Function不能动态执行代码
globalThis 修改全局对象已冻结

错误处理

script_error_mode

模式行为适用场景
log-and-continue(默认)脚本报错时记录 warn 日志,请求以原始 body 继续脚本失败不应阻断请求
log-and-reject脚本报错时拒绝请求,返回网关错误脚本正确性至关重要(如安全脱敏)

常见错误

错误原因解决
transform() must return a value某个 return 路径忘了返回 body每个 return 都必须返回 body
TooManyOperations超过操作数上限(默认 2000)优化循环
TypeError访问 null/undefined 的属性json_path()in 运算符检查
ReferenceError使用未定义的变量或函数检查拼写

提前返回时必须返回 body

javascript
function transform(body, context) {
    // ✅ 正确
    if (!body.messages) return body;

    // ❌ 错误:return 无值 → 脚本静默失败
    if (!body.messages) return;

    body.messages[0].content = "modified";
    return body;
}

脚本测试

部署前先测试脚本。测试接口 POST /console/api/scripts/test 需要控制台认证——用环境变量 $CONSOLE_TOKEN 带上(它不是上游访问密钥,是控制台 API 凭证)。拿法二选一:

获取 CONSOLE_TOKEN

方式 1:配 CONSOLE_SECRET_KEY(推荐脚本 / CI 用)——设环境变量 CONSOLE_SECRET_KEY,控制台把它当 Bearer token 用,长期有效、不怕过期:

bash
# 启动网关时注入
docker run -d -e CONSOLE_SECRET_KEY="my-secret-key-xxx" ... <>

# 测试脚本时带上
export CONSOLE_TOKEN="my-secret-key-xxx"

方式 2:用控制台账号登录拿 session token——不配 CONSOLE_SECRET_KEY 时走这条。POST /console/api/login 用账号密码登录,返回的 token 字段即 session token(默认 24 小时有效,调用会滑动续期):

bash
export CONSOLE_TOKEN=$(curl -s http://localhost:7890/console/api/login \
  -H "Content-Type: application/json" \
  -d '{"username":"protoflux","password":"你的密码"}' | jq -r .token)

CONSOLE_SECRET_KEY 与登录密码(CONSOLE_PASSWORD)相互独立,可只配其一。详见 控制台登录与角色

bash
curl -X POST http://localhost:7890/console/api/scripts/test \
  -H "Authorization: Bearer $CONSOLE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "script": "function transform(body, context) { body.model = context.upstreamModel; return body; }",
    "body": {"model": "gpt-4o", "messages": []},
    "context": {
      "clientModel": "gpt-4o",
      "upstreamModel": "gpt-4o-2024-05-13",
      "upstreamName": "openai",
      "sourceProtocol": "OpenAIChatCompletions",
      "targetProtocol": "OpenAIChatCompletions",
      "stream": false
    }
  }'

响应:

json
{
  "result_body": {"model": "gpt-4o-2024-05-13", "messages": []},
  "execution_time_ms": 0.12
}

POST /console/api/scripts/test。需要控制台 token 认证。

性能建议

性能与内存

脚本开销主要来自 JSON 序列化,耗时随 body 线性增长。after 槽大 body OOM 反模式、耗时参考与写法建议见 脚本性能与内存

常见问题

Q:脚本在控制台界面哪里配? 上游详情页和模型详情页都有「请求脚本」「响应脚本」输入框。也可以直接通过 Console API 设置。

Q:脚本改了 body.model,为什么路由没变?body.model 只改请求体的字段,不改路由。要切换路由用 context.useModel("模型名")

Q:流式请求的响应脚本生效吗? 暂不支持流式响应的脚本。请求脚本对流式请求有效,但响应脚本仅在非流式时生效。

Q:脚本报错了但请求正常通过? 默认的 log-and-continue 模式下,脚本报错不会阻断请求。查看 warn 日志了解报错原因。如需脚本必须成功,改用 log-and-reject

Q:context.headers 里为什么没有 Authorization? 安全设计:authorizationcookiex-api-key 等敏感 headers 在脚本可见之前已被移除,防止凭证泄露。

Q:怎么调大操作数上限?SCRIPT_MAX_OPERATIONS 可调。但建议先优化脚本——TooManyOperations 通常意味着循环复杂度过高。

下一步脚本 API 参考 看完整内置函数表;写第一个脚本变换 看入门结构;环境变量配置参考 看全部环境变量;审计与安全配置 看其他安全设置。