在 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:
二者通过 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) + '...'); }); });});// 启动 workerworker.start();
? 关键注意事项:
总结:告别 rest.all('*') 的副作用陷阱,拥抱 response:bypass + request:unhandled 生命周期事件组合——这是 MSW 中实现安全、可靠、高性能网络监控的唯一正确路径。