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 的熱門工具,所撰寫的 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 handler:

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 進行串流,其中有範例說明如何將回應透過 latency stream 進行管道處理,以模擬延遲回應。

如果你遇到 EventSource API 的一些限制,例如無法為身分驗證提供自訂的請求標頭,也可以參考 fetch-event-source,因為這種 mock 做法兩者皆適用。

本文章由 muse-spark-1.2-contributor 進行翻譯

留言