在真机上做模拟正是大多数方案崩溃的地方:桩服务器跑在笔记本上,手机得能连到它,应用还得指向它。Busymate DevTools 把模拟直接放进抓包链路。一条拦截规则监视每一个匹配方法和「主机加路径」模式的请求,并亲自回应匹配到的请求——一个合成的错误、一次掐断的连接,或者一个看起来和源站回复一模一样的模拟成功。上游服务器从未被联系。
规则在两处强制执行,因此每种连接模式都被覆盖:服务浏览器、通过代理的 Android 以及 PAC 模式 iOS 的代理服务器,还有 VPN 模式 iOS 的设备端 VPN 隧道。全局规则应用于每台设备;按设备的规则叠加其上。改动通过 Realtime 推送,所以你保存的规则无需重连就在手机上生效。
你需要
一部已经在抓包的手机,以及你想伪造的端点。
一部已配对、已开启抓包的手机——先按 iPhone 或 Android 指南操作。
该设备 SSL 代理列表中的 API 主机。按路径匹配的规则只能在已解密的主机上看到路径。
你想回应的那次调用的方法、主机和路径,以及你的应用期望收到的响应体。
仅脚本变体需要:你的角色具备管理员级别的脚本权限。普通 Mock 规则不需要特殊角色。
按顺序
第一到第四步给你一个固定的模拟。第五和第六步覆盖固定响应体做不到的两种情况:只触发一次,以及动态计算答案。
- 01
确认主机已被解密
打开仪表盘信息流,找到一条发往该端点的真实请求。如果那一行显示了解密的正文,就可以开始了。如果主机仍显示为加密,把它加入设备的 SSL 代理列表——通过该行的主机操作,或在设备设置里——然后再触发一次调用。对于以加密方式通过的主机,执行器只能匹配主机名;路径不可见,所以精确到路径的模拟永远不会触发。
- 02
打开 Blocks 并添加规则
从设置导航打开 Blocks 页面创建全局规则,或进入设备再进入 Blocks,创建只对这部手机生效的规则。添加一条规则,填入方法——或留空以匹配任意方法——以及模式。模式与断点使用相同的「主机加路径」通配符:主机、一个斜杠、路径,在会变化的段落处放一个星号。
- 03
选择 Mock 并塑造响应
把动作设为 Mock。Block 用来让调用失败,Drop 让它看起来像网络消失了,而 Mock 是用来满足它的:设置状态码——默认 200——应用会检查的头部,以及响应体。给它你的应用能解析的 Content-Type;收到文本回复的 JSON 客户端一个字节都读不了就会失败。保存为 JSON 后,规则长这样。
一条用固定响应体回应功能开关调用的 Mock 规则 json{ "enabled": true, "method": "GET", "pattern": "api.example.com/v1/feature-flags", "action": { "type": "mock", "status": 200, "headers": { "Content-Type": "application/json" }, "body": "{\"flags\": {\"newCheckout\": true}}" } } - 04
保存、触发调用并检查信息流
保存规则并使用应用。下一条匹配的请求会在从不离开抓包链路的情况下得到回应,并且仍然出现在你的信息流里——标记为已模拟,这样你能确切看到伪造了什么,并确认规则做了你期望的事。应用只看到一个普通的服务器回复:合成响应不携带任何内部或识别性头部,所以响应中没有任何东西会暴露拦截。
用完后用启用开关关闭规则。禁用的规则不消耗任何资源,并为下次保留原样。
- 05
用运行次数上限让它只触发一次
有些模拟只能发生一次。经典场景是一个合成的 401,让应用以为令牌过期从而执行刷新流程——如果每个请求都这么回应,应用就会刷新、重试、再收到一个 401,无限循环。Max runs 字段限制规则可以触发的次数;达到上限时它自动禁用,编辑器显示「自动禁用」标记,与你自己关掉的规则区分开。
计数按设备记录,并在重连和应用重启后保留,所以上限为一的规则在那部手机上只触发一次,而不是每个会话一次。带上限的全局规则只在耗尽次数的设备上被抑制,在机群的其他手机上继续触发。你也可以用自然语言让 BusyBro 在某个主机上做一次性的模拟 401,它会写出同样的规则。
一次性的 401——和普通模拟一样,只是加了上限为一 json{ "enabled": true, "method": "GET", "pattern": "api.example.com/v1/me", "action": { "type": "mock", "status": 401, "headers": { "Content-Type": "application/json" }, "body": "{\"error\": \"token_expired\"}" }, "maxRuns": 1 } - 06
用脚本计算响应体
Mock 响应体是一个冻结的字符串。当答案必须依赖请求——回显一个 id、一个时间戳、往真实回复里改一个字段——把规则的动作切换为 Script,或在 Settings 然后 Scripts 下创建独立脚本。你会得到一个对请求、响应和辅助对象都有自动补全的代码编辑器,以及一个 Test 面板,它把你的脚本跑在一条真实抓到的条目上,展示前后差异,而不触碰实时流量。这次试运行使用与线上代理完全相同的沙箱,所以测试通过就意味着线上可用。
抛出异常或超时的脚本会「失败即放行」:原始字节被转发,条目在检查器中被标记,所以坏掉的脚本永远不会卡住连接或向应用暴露自己。脚本属于管理员级别,因为它们在抓包链路中运行任意代码。
一个用计算出的 JSON 响应体短路的请求钩子 javascriptfunction onRequest(req) { if (req.path.startsWith("/v1/feature-flags")) { // computed per request — the upstream is never contacted return Response.json({ flags: { newCheckout: true, seed: Date.now() } }, { status: 200 }); } // no return → forward unchanged }
可能出现
看起来失效的规则几乎总是在匹配它看不见的东西。
规则从不触发
检查该设备上主机是否已解密——路径模式需要这一点——然后检查模式拼写以及方法是否匹配或为空。真实请求所在的信息流行显示了可直接复制的确切主机和路径。
应用卡在刷新循环里
你的合成 401 在每个请求上都触发。把 Max runs 设为 1,规则在第一次命中后自动禁用,重试的请求就能到达真实服务器。
应用拒绝模拟的回复
通常是缺少 Content-Type 头部,或响应体结构与客户端解析的不一致。从检查器中复制一条真实抓到的响应的头部和正文作为起点。
规则显示「自动禁用」标记
它在这台设备上用完了运行次数。清空 Max runs 或重新启用规则即可再次武装。
脚本运行了,但回复是真实的
脚本抛出了异常或超时,于是失败放行。在检查器中打开该条目——错误标记带有消息和行号——在编辑器里修复,然后在重新启用前用 Test 面板对同一条目再跑一次。
大家常问
应用能察觉自己被模拟了吗?
通过检查响应是察觉不到的。模拟的 200 或被拦截的 403 不携带任何识别性头部,看起来就像源站的普通回复。可见性是单向的:被标记的条目只出现在你的信息流里。
这在 VPN 模式的 iOS 上有效,还是只通过代理有效?
都有效。同一个规则引擎运行在 iOS VPN 隧道内和代理服务器上,所以两种模式的 iOS、通过代理的 Android 和浏览器都遵守规则。
修改规则后需要重新部署什么吗?
不需要。规则存在于通过 Realtime 推送到设备的同一份设置中,所以保存后会立即应用于新连接。已经打开的长连接会保留它开始时的配置,直到重连。