
在 MSW 中,onUnhandledRequest 无法捕获真实响应;正确做法是利用生命周期事件 response:bypass 配合 request:unhandled,实现对未被拦截请求的完整请求-响应链路监控与日志记录。
在 msw 中,`onunhandledrequest` 无法捕获真实响应;正确做法是利用生命周期事件 `response:bypass` 配合 `request:unhandled`,实现对未被拦截请求的完整请求-响应链路监控与日志记录。
MSW(Mock Service Worker)的核心设计原则是「声明式拦截」——仅对显式定义的 rest.get()、rest.post() 等 handler 进行响应模拟,其余请求默认透传至真实网络。但许多端到端测试或调试场景中,开发者需要观察这些“漏网之鱼”:例如记录第三方 API 调用的实际响应体、状态码、耗时,用于后续断言、问题复现或生成测试存根(fixtures)。
⚠️ 注意:onUnhandledRequest 不是监控钩子,它仅控制未匹配请求的行为(如 warn/error/bypass),不参与请求执行流程,也无法访问原始响应对象。试图在此回调中调用 fetch() 或修改响应将破坏请求时序,且引入重复请求风险(如 rest.all('*') + ctx.fetch() 方案),不推荐用于生产级监控。
✅ 推荐方案:使用 MSW 提供的 Lifecycle Events(生命周期事件),它是专为网络可观测性设计的底层 API:
- request:unhandled:当请求未被任何 handler 匹配时触发,携带完整的 Request 实例和唯一 requestId;
- response:bypass:当透传请求收到真实响应后触发,携带 Response 实例和对应 requestId。
二者通过 requestId 可精确关联请求与响应,形成完整链路。以下为可直接运行的监控示例:
import { setupWorker } from 'msw';
const worker = setupWorker(
// 定义你的 mock handlers...
// rest.get('/api/users', () => res(ctx.json([...]))),
);
// 监听未处理请求(获取请求详情)
worker.events.on('request:unhandled', ({ request, requestId }) => {
console.log(`[UNHANDLED REQUEST] ${request.method} ${request.url}`);
// 可选:保存请求头、body、时间戳等
});
// 监听透传响应(获取真实响应)
worker.events.on('response:bypass', (response, requestId) => {
// 关联请求(需自行维护映射表,或仅记录关键字段)
console.log(`[BYPASS RESPONSE] ${response.status} ${response.statusText}`);
// ✅ 安全地读取响应体(注意:仅限 text/json 类型,避免多次 body 消费)
response.clone().json().then(data => {
console.log('[RESPONSE BODY]', data);
// 示例:写入文件供后续分析
// fs.writeFileSync(`logs/${requestId}.json`, JSON.stringify({ response, data }, null, 2));
}).catch(() => {
response.clone().text().then(text => {
console.log('[RESPONSE TEXT]', text.substring(0, 200) + '...');
});
});
});
// 启动 worker
worker.start();
? 关键注意事项:
- response:bypass 中的 Response 对象不可重复读取 body(如多次调用 .json() 会报错),务必使用 response.clone() 创建副本;
- 若需持久化日志(如写入文件),建议在 Node.js 环境(如 Playwright/Vitest)中使用 fs 或 fs-extra,浏览器环境可导出为 Blob 下载;
- requestId 是 UUID 字符串,可用于跨事件关联,但 MSW 不自动存储请求上下文,如需完整请求体,应在 request:unhandled 中提前解析并缓存(注意 request.body 流只能读一次);
- 此方案零侵入、无额外网络开销、不干扰原有请求流,是官方推荐的监控范式。
总结:告别 rest.all('*') 的副作用陷阱,拥抱 response:bypass + request:unhandled 生命周期事件组合——这是 MSW 中实现安全、可靠、高性能网络监控的唯一正确路径。










