Consuming the stream from a client

A stream is only as good as the client reading it. Browsers ship EventSource for GET-based SSE, but we use POST to send a prompt body, which rules out EventSource. For this workshop we read the stream with curl first, then with a tiny fetch-based JavaScript consumer.

terminal
bash
curl -N -X POST http://localhost:8000/deploy-patterns/chat/stream \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Write a haiku about a slow proxy"}'

curl -N disables output buffering so you see each event as it arrives. Without -N the shell would hold the response until the stream ended and the streaming illusion would collapse.

client.js
javascript
async function streamChat(prompt) {
  const res = await fetch("/deploy-patterns/chat/stream", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ prompt }),
  });
  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    const text = decoder.decode(value);
    for (const line of text.split("\n")) {
      if (!line.startsWith("data: ")) continue;
      const event = JSON.parse(line.slice(6));
      if (event.content) process.stdout.write(event.content);
      if (event.done) return;
    }
  }
}

A minimal fetch-based SSE reader. We read the response body as a stream, decode the chunks, split on newline, and parse the data lines. This is the pattern any frontend framework wraps under the hood.

AI prompt: Ask an AI to review your SSE client

Loading practice…

Quiz: Quiz

Loading practice…

Checkpoint: SSE checkpoint

Loading practice…