事情本身不复杂,线索都在日志里。前端用 EventSource 收流式回答,把 event.data 直接 JSON.parse,控制台报 Unexpected token 'd',抓包看到内容开头是 data: 加一段 JSON,说明前缀根本没被剥掉。
第一反应是「服务端 Content-Type 写成了 text/plain,浏览器不按 SSE 解析」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。网关把 SSE 又包了一层,前端拿到的是原始行。少数情况下是用的不是标准 EventSource,而是自己按行读流。
还有一种情况,中间的注释心跳行没有过滤。
动手时先确认响应头是不是事件流
curl -I http://10.0.0.8:8000/v1/chat/completions
接着在客户端剥掉 data 前缀再解析
node sse_parse.js --strip-prefix
跳过注释行与结束标记
node sse_parse.js --skip-comment --done '[DONE]'
等前面都确认过,再用 curl 直接看原始流对照
curl -N http://10.0.0.8:8000/v1/chat/completions -H 'Content-Type: application/json' -d @req.json
怎么算真的好了,看的是同一批现象。前端解析不再抛 Unexpected token,首字延迟正常,最后一条结束标记能被识别并关闭连接。
这里还有个坑。自己实现 SSE 解析要同时处理 data 前缀、注释行和结束标记,少一条都会在某个网关后面出错。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
