Insomnia 与 Bruno 本地优先接口调试手册
请求在你的电脑上成功,流水线却找不到它
最常见的失败不是接口返回 500,而是同事拉下仓库后根本看不到请求,或者 CI 能读到 collection,却把 {{baseUrl}} 原样发了出去。另一个危险信号是:为了让流水线先跑起来,有人把 token 填进环境文件并提交;请求绿了,凭证也进入了 Git 历史。
这类事故要先拆成三个对象:请求定义存在哪里,非敏感环境配置存在哪里,Secret 在运行时从哪里注入。Insomnia 和 Bruno 都能发送 HTTP 请求,但数据模型不同:Insomnia 可在 Local Vault、Cloud Sync 和 Git Sync 之间选择;Bruno 以本地 collection 目录和可审查文本文件为中心。GUI 里能点通,只证明当前设备的当前状态可用,不能证明另一个工作站或无界面 runner 能重建相同状态。
第一次操作前,先准备一个不会修改业务数据的测试接口、一个低权限测试身份,以及企业代理和根证书的获取方式。不要拿生产管理员 token 做教程实验,也不要在排障期间打开会记录请求头的屏幕共享、终端转录或 CI debug 日志。
安装桌面端和命令行
Insomnia 13.0.2 是当前稳定基线,提供 macOS、Windows 和 Linux 64 位桌面应用;官方下载入口和支持平台见 Insomnia 文档 与 Insomnia 13.0.2 发布页。团队协作同一项目时应固定同一主版本,因为官方没有 LTS 发行线,主版本可能改变导出格式、CLI 参数或插件 API;升级策略见 Insomnia 版本政策。
安装后先记录实际版本,不要用网页上的“最新版”替代运行证据:
inso --versionInso CLI 应从与桌面端同一条发布线安装:macOS 可执行 brew install inso,Windows 和 Linux 使用官方发布的压缩包,CI 也可固定 kong/inso 镜像的版本或 digest。旧 npm 包 insomnia-inso 已标记废弃,不能再作为安装入口。官方发布同时提供 Inso 二进制、SBOM 和 provenance;安装步骤与命令参数分别见 Inso CLI 安装文档 和 Inso CLI 参考。
Bruno 桌面端支持 macOS、Windows 和 Linux,Windows 还提供 winget、Chocolatey 与 Scoop 入口;完整选项见 Bruno 安装文档。例如:
winget install Bruno.Brunobrew install brunoBruno 桌面端和 CLI 当前稳定基线均为 3.5.2。CLI 是独立的 Node.js 包;官方建议使用 Node.js 18 或更高版本,并优先使用受支持的 LTS 线。个人机器可以全局安装,项目和 CI 则应保存为精确开发依赖:
npm install --global @usebruno/cli@3.5.2
bru --version
# 项目内安装,由 lockfile 固定实际解析结果
npm install --save-dev --save-exact @usebruno/cli@3.5.2
npx --no-install bru --version桌面端版本、CLI 版本和 collection 格式要一起纳入基线。只锁桌面端而让 CI 每次安装浮动的 latest,会把格式迁移和 sandbox 默认值变化直接带进流水线。
先把数据放对位置
Insomnia 的三种持久化选择
Insomnia 存储文档 对三条主路径给出了不同的协作含义:
| 存储方式 | 数据位置与协作方式 | 需要承担的治理成本 |
|---|---|---|
| Local Vault | 项目数据保留在设备本地 | 设备备份、离职交接、磁盘加密 |
| Git Sync | 项目资源以 YAML 存入 Git 仓库,由标准分支和合并流程协作 | 冲突审查、仓库权限、Secret 扫描 |
| Cloud Sync | 通过 Insomnia 云端同步和协作 | 组织权限、席位、数据驻留与采购评估 |
Scratch Pad 也保存在本地,但更适合个人临时请求,不应成为团队资产的唯一副本。存储类型可以转换,但转换本身会改变唯一事实来源;从 Cloud Sync 转为 Local Vault 或 Git Sync 前,应让所有协作者先拉取最新变更,否则只存在云端的修改可能丢失。
Git Sync 不是把一个不透明数据库塞进仓库。官方说明项目资源以 YAML 文件保存,Insomnia 在应用内充当 Git 客户端,分支保护仍由 Git 服务端执行,Inso 也能读取仓库中的本地数据。组织中的 Git Sync 项目不会自动出现在其他成员账号下;每名协作者都要创建自己的 Git Sync 项目并连接同一远程仓库,真正的共享边界仍是 Git 仓库权限。仓库可能出现仅用于结构或兼容性的 metadata 变更,评审时要区分请求语义变化和工具元数据变化,不能看到“大段 YAML”就直接批准。详情见 Git Sync 数据模型。
Bruno 的 collection 就是工作目录
Bruno 的 collection 以普通文件组织,适合与业务代码一起走分支、PR 和 code owner。一个可维护的目录可以是:
api-tests/
bruno.json
health/
get-health.bru
users/
get-me.bru
environments/
local.example.bru
ci.bru
README.mdbruno.json 标识 collection 根目录,请求与文件夹结构决定执行范围。环境、collection、folder、request 和 runtime 变量会按作用域参与解析;变量类型和存储位置见 Bruno Variables。环境名相同不代表内容相同,团队必须在 PR 中审查 baseUrl、租户、超时和请求顺序等非敏感字段。
不要把“纯文本”理解为“天然安全”。.bru、JSON、导出文件、脚本和测试断言都可以容纳 token、Cookie、内部 URL 或响应样本。Git 只提供历史,不会替你识别秘密。
用同一个失败做正反实验
准备一个只读的 /health 请求,并让服务端在响应头返回 x-request-id。先故意把环境中的 baseUrl 写成不存在的主机:
baseUrl = https://does-not-exist.invalid在桌面端发送请求。预期不是 4xx 或 5xx,而是 DNS/连接类错误,并且服务端没有 request id。这是“请求尚未抵达应用”的证据。
然后把 baseUrl 改成测试环境地址,但注入一个已撤销的低权限 token。预期请求能完成 TLS 与 HTTP 交换,返回 401 或 403,响应头可能带 request id,服务端访问日志也应有同一标识。这证明网络已通,失败位于认证或授权层。
最后由 Secret Manager 或本地私有环境注入有效测试 token。预期是明确的成功状态码、约定的响应 schema 和可关联的 request id。不要只看绿色图标;在 request test 中断言状态码和关键字段,并确认响应不是网关兜底页。
这三个实验不能被“我本机点过一次”替代。它们分别产出 DNS/连接错误、认证失败响应和业务成功证据,能让接手者判断故障发生在传输层、身份层还是应用层。
环境变量和 Secret 不是一回事
Insomnia 的环境可以承载 base URL、租户代号和测试开关。Secret 变量只能放在 private global sub-environment 中,默认不会同步或导出,并由 vault key 解锁;vault key 丢失后只能重置,已存 Secret 会被删除。Secret 默认也不暴露给脚本,开启脚本访问会扩大插件和脚本的权限面。具体行为见 Insomnia Environments。
需要让 CLI 在无界面环境取密钥时,优先接 AWS Secrets Manager、GCP Secret Manager、Azure Key Vault 或 HashiCorp Vault,通过 runner 身份和环境变量提供认证,不把云密钥写进 Insomnia YAML。支持方式见 Insomnia External Vault。
Bruno 桌面端标记为 Secret 的变量保存在本机加密状态中,值不会写入环境文件或 collection 导出,因此换机或进入无界面 runner 后不能凭仓库自动重建。CI 应从平台 Secret 注入运行时变量。Bruno 还支持 collection 根目录下、已加入 .gitignore 的 .env 文件,并通过 process.env 引用;这种方式能让 GUI 与 CLI 使用同一引用,但 .env 本身仍是明文临时文件,必须限制权限和生命周期。
先在受版本控制的 environments/ci.bru 中只保存引用,不保存值:
vars {
baseUrl: {{process.env.API_BASE_URL}}
apiToken: {{process.env.API_TOKEN}}
}runner 再创建仅本次任务可读的 .env,并保证命令失败时也会删除:
umask 077
mkdir -p reports
BRUNO_DOTENV="$PWD/api-tests/.env"
trap 'rm -f "$BRUNO_DOTENV"' EXIT
printf 'API_BASE_URL=%s\nAPI_TOKEN=%s\n' "$API_BASE_URL" "$API_TOKEN" > "$BRUNO_DOTENV"
cd api-tests
npx --no-install bru run \
--env ci \
--tags smoke \
--bail \
--reporter-junit ../reports/bruno.xml \
--reporter-skip-all-headers \
--reporter-skip-bodyBruno 会把 .env 中的值视为 Secret 并在内置报告中掩码,但报告仍显式跳过全部 Header 和请求、响应 Body,形成第二层保护。--env-file、--env-var、reporter 脱敏和 sandbox 参数见 Bruno CLI 选项;.env 的引用方式见 Bruno Secret 管理。即使 CI 平台会掩码 Secret,也不要假设它能识别 URL 编码、截断值、响应回显或派生 token。
让 GUI 和 CLI 读取同一份资产
Insomnia Git Sync 项目可由 Inso 从工作目录读取。先在仓库根目录确认 CLI 实际看到的数据,再指定 collection:
inso --ci --workingDir api-tests/insomnia run collection "Health Smoke"--ci 会禁用交互提示,--workingDir 可指向 .insomnia 目录、数据库导出或 YAML 文件。若报“找不到 collection”,先检查工作目录和标识符,不要重新在 CI 里导入一份脱离 Git 的副本。
Bruno 应先进入 collection 根目录再运行全部请求;指定文件夹时默认不递归,嵌套请求需要 -r。一个请求在 GUI 中可见而 CI 未执行,常见证据就是执行摘要的请求数少于目录中的 smoke 请求数:
cd api-tests
npx --no-install bru run health -r --env ci --tags smoke --bailBruno CLI 3.x 默认使用 Safe sandbox。需要文件系统、外部 npm 包或系统能力的脚本会在 Safe 模式失败,这是权限隔离生效,不是“CI 环境坏了”。只有经过代码审查的受控 collection 才能显式启用:
bru run api-tests --sandbox=developerDeveloper 模式扩大了脚本读取文件、环境和依赖的能力。更稳妥的做法是先移除不必要的系统访问,让 smoke 保持 Safe;无法移除时,再把 developer 权限、依赖锁定和执行 runner 写进安全评审。
代理、CA 与 mTLS 要分别验证
企业网络里“桌面端成功、CLI 失败”通常不是请求内容差异,而是代理和信任库来源不同。诊断顺序应固定:
确认目标域名是否必须走代理,以及 NO_PROXY 是否错误绕过。确认代理自身若为 HTTPS,客户端是否信任代理证书。确认目标服务证书链是否被企业中间人证书重新签发。
确认 mTLS 客户端证书、私钥、密码和目标主机匹配。对比桌面端与 CLI 的代理模式、CA 文件和客户端证书配置。
Bruno GUI 的 Proxy 默认为 Off,可切换为 On 或 System;SSL/TLS、Custom CA 和 Cookie 也有独立设置,见 Bruno Settings。CLI 要显式携带同等配置:
bru run api-tests \
--cacert "$CORP_CA_FILE" \
--client-cert-config "$CLIENT_CERT_CONFIG"--noproxy 会同时关闭 collection 和系统代理,不能把它当作通用修复。--insecure 只能用于一次性对照实验:若加上后连接成功,得到的是“证书验证路径有问题”的证据;正确修复是补齐 CA 或服务端证书链。
Insomnia 支持按域名绑定客户端证书;官方列出的桌面格式差异是 macOS 使用 PFX、Windows/Linux 使用 PEM,见 Insomnia 认证与客户端证书。证书和私钥只保存路径或 Secret 引用,不进入 collection 导出、Git 仓库或 CI artifact。
CI 中保留可审计的最小证据
一条可审计 smoke 至少要固定 CLI 主版本、collection 路径、环境来源、请求选择规则、超时或中止策略、退出状态和脱敏报告。不要在每次流水线里全局安装浮动版本:把 CLI 放进项目开发依赖并由 lockfile 固定,使用 npx --no-install bru 或等价的包管理器命令执行。
报告只需回答:运行了哪些请求、哪些断言失败、耗时多少、对应哪个 request id。Header 和 body 默认不归档;确需保留时使用测试数据、最小字段和短保留期。HTML、JSON、JUnit 与控制台输出都按敏感资产处理。
Insomnia 的 CI 任务应在启动时打印 Inso 版本和 Git 提交号,但不打印环境变量;Bruno 任务还应记录 sandbox 模式和实际执行请求数。若 GUI 与 CI 数量不一致,先停下发布,检查 tag、递归参数、禁用请求和 collection 根目录。
清理、回滚与退出路径
临时排障结束后,删除导出的 collection、HAR、JUnit/HTML 报告、临时环境文件、客户端证书副本和 trace;撤销测试 token,并检查 shell history、CI artifact 与问题单附件。Secret 一旦进入 Git,删除工作区文件不算完成:必须轮换凭证,再按仓库治理流程清理历史。
工具升级出现 collection 迁移或脚本行为变化时,不要直接降级后继续写入。先停止编辑,保留仓库提交或脱敏导出,在样例分支上用旧版与候选版 CLI 跑同一 smoke;确认格式可逆后再决定回退桌面端、回退 collection 提交,还是完成迁移。Insomnia Git Sync 的提交历史和 Bruno 的文本文件都能提供回滚点,但前提是 Secret 没有混入提交。
停用工具时,将仍有效的请求定义迁移到 OpenAPI、另一 collection 格式或最小 curl smoke,撤销 Cloud/组织成员和 OAuth 授权,删除本地 vault、缓存与证书副本,再归档不含 Secret 的最后版本。仅卸载桌面应用不会撤销云端席位、Git 凭证或外部 vault 权限。
选型看资产控制权,不看按钮多少
| 决策信号 | Insomnia 更合适 | Bruno 更合适 |
|---|---|---|
| API 设计与请求调试一体化 | Design Document、Collection、lint 与 Inso 流程 | 通常从 OpenAPI 导入后维护 collection |
| 数据控制 | Local Vault、Git Sync、Cloud Sync 可选 | 本地优先、collection 文件直接进 Git |
| 代码评审体验 | Git Sync YAML 与 metadata 需要约定 | 文本请求和目录结构更贴近日常 PR |
| 组织身份治理 | Enterprise 提供 SSO、SCIM、团队和存储控制 | 高级 Secret/Vault 与商业能力需核对授权计划 |
| 无界面自动化 | Inso 读取本地项目或导出 | bru 直接运行 collection 目录 |
| 脚本权限 | 插件、脚本与 vault 访问需单独治理 | Safe/Developer sandbox 边界明确 |
价格、席位和企业功能会变化,不应固化成架构常量。采购时以 Insomnia 能力矩阵 和 Bruno 应用内 License/官方授权页面为依据,逐项验证 Git Sync 人数、RBAC/SSO、Vault、审计和支持承诺。开源桌面端可用不等于组织协作、云同步和企业治理没有成本。
长期治理的是请求资产,不是客户端偏好
接口 collection 会持续增长。全部请求每次都跑,会拉长流水线并增加测试账号、网关限流和第三方调用成本;完全不跑,又会让 collection 变成无法执行的文档。团队应把请求分成 PR smoke、环境回归和人工诊断三层,用 tag 与目录控制执行范围,并给有副作用的请求加隔离租户、幂等键或显式禁用。
每个季度抽样检查:CLI 与桌面主版本是否一致,废弃环境是否删除,Secret 是否仍由运行时注入,证书是否临近轮换,report artifact 是否过度保留,插件和 Developer sandbox 是否仍有必要,闲置席位和云项目是否回收。collection owner 负责请求与断言,平台 owner 负责 runner、代理和 Secret 注入,安全 owner 负责扫描、证书和权限审计;没有 owner 的 collection 很快会同时失真和泄密。
最终验收不看“谁更好用”,而看同一份请求能否被桌面端打开、被 CLI 从仓库重建、在 CI 中产生稳定退出状态和最小证据,并在成员离开、证书轮换、工具升级或采购终止时完整退出。
