whistle 如何用脚本处理请求响应并避开常见坑?
whistle 的脚本能力适合处理规则表达不了的逻辑,比如按请求参数动态改 header、根据用户身份返回不同 mock、给响应体追加字段,或者把线上接口临时改造成前端需要的数据形状。规则更像声明式配置,脚本则是命令式处理;能用规则解决的别急着写脚本,因为脚本越多,调试成本和副作用也越高。它的边界也很明确:脚本运行在代理链路里,任何慢逻辑都会拖慢请求,任何不严谨的匹配都可能影响无关流量。
先准备一个本地脚本文件,例如 change-user.js:
javascriptmodule.exports = (req, res) => { req.headers['x-debug-user'] = '10001'; };
在 Rules 中绑定到目标接口:
txthttps://api.example.com/user reqScript:///Users/me/whistle/change-user.js
响应处理通常用于 mock 或修正字段,示例只处理 JSON,避免误伤图片、HTML 或二进制内容:
javascriptmodule.exports = (req, res) => { const type = res.headers['content-type'] || ''; if (!type.includes('application/json')) return; const data = JSON.parse(res.body || '{}'); data.debug = true; res.body = JSON.stringify(data); };
脚本最好和规则一起放进项目的调试目录,文件名说明用途,例如 mock-login-expired.js、add-debug-header.js。团队协作时要写清楚启用条件,不要让别人打开 whistle 后默认命中你的个人调试逻辑。
追问
reqScript 和 resScript 应该怎么选?
需要在请求发出前改 URL、header、cookie 或 body,就用 reqScript;需要在服务端返回后改状态码、响应头或响应体,就用 resScript。取舍点在于问题发生的位置:鉴权参数错了通常改请求,接口字段不满足前端联调通常改响应。踩坑最多的是在 resScript 里试图修正已经发出去的请求参数,这时后端早就处理完了。判断不清时先在 Network 里看请求和响应,确认要动哪一侧。
脚本里处理 JSON 响应要注意什么?
第一步永远是判断 content-type,不要默认所有响应都是 JSON。边界包括空响应、压缩响应、流式响应、图片和下载文件,这些内容被强行 JSON.parse 很容易报错或损坏。更稳的写法是只匹配明确接口,并对解析失败做兜底,不要让一个异常中断整个代理处理。调试阶段可以打印 URL 和错误信息,但长期使用要减少日志,避免控制台被刷屏。
为什么不建议所有 mock 都用脚本写?
脚本很灵活,但灵活也意味着行为不够直观。简单固定响应用 resBody 或 Values 更容易维护,复杂条件分支、按参数返回不同数据时再上脚本。取舍标准是“别人打开规则能不能一眼看懂”,如果必须读几十行 JS 才知道接口返回什么,维护成本就偏高。常见坑是脚本越写越像小服务,最后不如直接起一个本地 mock server。
脚本影响了无关请求怎么办?
先收窄 Rules 匹配范围,不要用过宽的域名或通配符挂脚本。脚本内部也可以二次判断路径、方法和参数,条件不满足立刻 return。边界是代理层没有业务上下文,不能只凭一个字段就假设请求属于某个页面。排查时先禁用脚本确认问题消失,再逐步恢复匹配条件和处理逻辑。
团队里怎么管理这些调试脚本?
建议把通用脚本放进仓库的 debug/whistle 目录,只提交脱敏、可复用的版本,个人临时脚本放在本机不共享。配置里不要写真实 token、内网账号或客户数据,必要时用环境变量或本地 Values 注入。取舍是共享脚本能提升联调效率,但也可能把个人调试假设扩散给全团队。每个脚本顶部写两三行用途、命中接口和关闭方式,比事后在群里解释更省时间。