Mock server-sent events (SSE) with msw

Alex O'Callaghan

使用 msw 模拟 Server-Sent Events(SSE)

原文由 Alex O'Callaghan 发布,订阅该博客

更新:MSW 已新增对模拟 Server-Sent Events 的一等支持——本文也获得了署名致谢,不过现在建议你直接查阅 MSW 文档


Server-sent events 允许服务端向前端应用推送事件流。它与 WebSocket 类似,但仅提供从服务端到客户端的单向连接。

ChatGPT 这样的生成式 AI 解决方案会利用 Server-sent events,在大语言模型生成响应的过程中以流的形式实时推送到客户端。随着生成式 AI 应用的普及,如何处理这类流式响应成为需要克服的一大挑战,它与典型的 REST API 有所不同。

Mock Service Worker 是一款流行的工具,用于编写可在不同框架、工具和环境中复用的 JavaScript API mock。在 Mintel,我们使用 mswStorybook、单元测试和其他开发环境编写 mock。

msw 已支持模拟 SSE 事件,而 对 WebSocket 的支持仍处于 Beta 阶段。例如,假设有如下用于建立 Server-Sent Events 连接的前端代码:

const source = new EventSource("http://example.com/stream");

source.onmessage = (event) => {
  console.log(`Message: ${event.data}`);
};

你可以编写如下 msw mock 处理器:

import { http, HttpResponse } from "msw";

const encoder = new TextEncoder();

const handler = http.get('http://example.com/stream', () => {
  const stream = new ReadableStream({
    start(controller) {
      controller.enqueue(
        encoder(
          `event:some-event\ndata:some data\n\n`
        )
      );
      controller.close();
    },
  });

  return new HttpResponse(stream, {
    headers: {
      "Content-Type": "text/event-stream",
    }.
  });
});

这个 mock 会返回单个 some-event 事件,其 event.data 中包含 "some data"。每条消息都应包含表示字段与值的多行文本,字段名与值之间用冒号分隔。消息之间则以一对换行符分隔。你可以进一步了解事件流消息格式

你还可以进一步了解使用 msw 实现流式响应,其中包含如何通过延迟流来处理响应以模拟延迟响应的示例。

如果你遇到了 EventSource API 的一些限制,例如无法为身份验证提供自定义请求头,也可以了解一下 fetch-event-source,因为这种模拟方式对两者都适用。

本文章由 muse-spark-1.2-contributor 进行翻译

评论