Whistle Mock流式JSON接口实战避坑指南:从响应头异常到完美渲染
最近在重构一个实时数据监控项目时,遇到了一个令人头疼的问题:明明已经用Whistle成功Mock了接口返回的JSON数据,页面却死活渲染不出来。控制台没有报错,Network里也能看到数据返回,但前端就是吃不下这口"饭"。经过一番折腾,终于发现是content-type这个响应头在作祟。今天就把这个排查过程完整分享出来,希望能帮到同样踩坑的朋友。
1. 问题现象:Mock成功但页面崩溃
那是一个风和日丽的下午,我正在为即将上线的数据看板准备Mock环境。按照常规操作流程:
- 在Whistle的Network面板中找到目标接口
/api/realtime/metrics - 右键复制URL,在Values中创建
metrics-mock.json文件 - 将准备好的测试数据粘贴进去
- 配置规则:
https://example.com/api/realtime/metrics file://{metrics-mock.json}
刷新页面后,Network里确实显示返回了我Mock的数据:
{ "cpu_usage": 45.2, "memory_usage": 78.1, "network_in": 1024, "network_out": 2048 }但诡异的是,前端页面就像没收到数据一样,图表区域一片空白。打开控制台,没有任何错误日志。这感觉就像你明明把饭端到了桌上,家人却说没看见——简直让人抓狂。
2. 排查过程:响应头里的魔鬼细节
2.1 对比真实与Mock接口的差异
既然数据已经返回,问题可能出在数据的"包装"上。我决定对比真实环境和Mock环境的接口响应:
真实接口响应头:
HTTP/1.1 200 OK Content-Type: text/event-stream;charset=UTF-8 Transfer-Encoding: chunked Connection: keep-aliveMock接口响应头:
HTTP/1.1 200 OK Content-Type: text/plain;charset=UTF-8 Content-Length: 132 Connection: keep-alive关键差异一目了然:真实接口使用的是text/event-stream,而Mock默认返回的是text/plain。这就是问题的根源!
2.2 为什么Content-Type如此重要?
流式JSON数据与普通JSON数据的区别就像自来水和瓶装水:
| 特性 | 流式JSON (text/event-stream) | 普通JSON (application/json) |
|---|---|---|
| 数据传输方式 | 持续流式传输 | 一次性完整传输 |
| 适用场景 | 实时监控、股票行情、聊天应用 | 普通API接口 |
| 前端处理方式 | 需要特殊的事件监听机制 | 直接JSON.parse解析 |
| 连接特性 | 长连接,服务器可主动推送 | 短连接,请求-响应模式 |
我们的前端代码正是基于EventSourceAPI来监听数据流的:
const eventSource = new EventSource('/api/realtime/metrics'); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); updateDashboard(data); };当响应头是text/plain时,EventSource根本不会触发onmessage事件,导致数据虽然返回了,但前端代码收不到通知。
3. 完整解决方案:Mock数据+正确响应头
3.1 配置自定义响应头
在Whistle的Values中新建metrics-headers.json:
{ "Content-Type": "text/event-stream; charset=utf-8", "Cache-Control": "no-cache", "Connection": "keep-alive", "Access-Control-Allow-Origin": "*" }3.2 更新Rules规则
将Mock规则调整为两条:
# 设置响应头 https://example.com/api/realtime/metrics resHeaders://{metrics-headers.json} # 设置Mock数据 https://example.com/api/realtime/metrics file://{metrics-mock.json}重要提示:Whistle规则是从上到下匹配的,确保响应头规则在Mock数据规则之前,否则可能被覆盖。
3.3 验证流式数据传输
刷新页面后,不仅数据正常显示,还能看到流式传输特有的行为:
- Network面板中显示请求状态持续处于"Pending"
- 响应类型显示为"eventstream"
- 数据以SSE(Server-Sent Events)格式传输
4. 高级技巧:动态Mock流式数据
对于需要模拟实时变化数据的场景,可以结合Whistle的resScript功能:
// 在Values中创建metrics-script.js const data = { cpu_usage: Math.random() * 100, memory_usage: 70 + Math.random() * 30, network_in: 500 + Math.random() * 1500, network_out: 500 + Math.random() * 1500 }; exports.handleResponse = (ctx, next) => { ctx.setHeader('Content-Type', 'text/event-stream'); ctx.setHeader('Cache-Control', 'no-cache'); ctx.setHeader('Connection', 'keep-alive'); // 模拟实时数据推送 let count = 0; const timer = setInterval(() => { if (count++ >= 10) { clearInterval(timer); ctx.end(); return; } data.cpu_usage = Math.random() * 100; data.memory_usage = 70 + Math.random() * 30; ctx.write(`data: ${JSON.stringify(data)}\n\n`); }, 1000); ctx.write(`data: ${JSON.stringify(data)}\n\n`); };对应规则:
https://example.com/api/realtime/metrics resScript://{metrics-script.js}5. 常见问题排查清单
遇到Mock流式接口不工作时,可以按照以下步骤检查:
确认响应头:
Content-Type是否为text/event-streamConnection是否为keep-aliveCache-Control是否设置为no-cache
检查前端代码:
- 是否使用
EventSource而非fetch/axios - 事件监听是否正确(
onmessagevsaddEventListener)
- 是否使用
验证Whistle规则:
- 规则顺序是否正确(响应头规则在前)
- 规则语法是否正确(特别是
resHeaders://和file://的用法) - 是否有多条规则冲突
数据格式验证:
- 流式数据每段应以
data:开头 - 每段数据以
\n\n结尾 - 数据应为合法JSON字符串
- 流式数据每段应以
这个项目最终上线后运行稳定,但那段调试经历让我深刻认识到:Mock不只是替换数据那么简单,理解协议和规范同样重要。特别是在处理特殊数据格式时,魔鬼往往藏在那些我们容易忽略的细节里。