Skip to learning content
Learning StudioCourses and practice
Experiences

Transport · SSE-compatible streams

Streaming Transport

A chat client needs a transport adapter that can turn UTF-8 bytes split at any point into typed events. Parsing, cancellation, and render timing should each have their own clear rules.

Evidence & limits
What the further reading establishes
The HTML event-stream format defines a one-way channel with named events, data fields, reconnect behavior, and UTF-8 framing.
What this lab runs
The fixed browser trace compares a stream that finishes with one cancelled after four tokens. It shows when the parser and generator stop, how many late events arrive, and whether resources are released.
What it does not prove
This stream runs locally. It doesn't recreate proxy buffering, reconnect fields, retry timing, or disconnects across regions.

Dataset

Token Event Trace

Source
Course-authored synthetic stream
License
Not separately licensed
Size
14 frames · adversarial chunk boundaries

Further reading

  • Server-sent events

    Primary · WHATWG HTML Standard · Living standard

    The official rules for event-stream framing, parsing, IDs, reconnection, and UTF-8 behavior.

  • Streams Standard

    Specification · WHATWG · Living standard

    Defines how readable streams, readers, queues, cancellation, and backpressure work.

  • Using server-sent events

    Guide · MDN Web Docs · Current

    Gives practical browser and server examples for event names, data fields, errors, and connection limits.

Lesson progressRestoring progress…

  1. CodeRestoring
  2. ExperimentRestoring
  3. CheckRestoring

Summary

Decode bytes before you parse frames. ReadableStream chunks are Uint8Array values, and a chunk can stop in the middle of a UTF-8 character. TextDecoder.decode(chunk, { stream: true }) holds onto those incomplete bytes. The practice parser starts after that step, so its chunk argument is decoded text, never raw bytes.

Hold text until the frame is done. Every SSE frame ends with a blank line. Add the leftover text from the previous chunk, emit each complete frame, and return the unfinished ending. This lesson handles LF or CRLF lines, one optional space after the field colon, and "message" as the default event name.

Turn wire fields into app events. The event field gives the type, and data lines hold a JSON payload. The transport adapter returns typed token, metrics, done, or error events. That way React never has to care about byte boundaries or callbacks specific to one backend.

One token across arbitrary chunksA chunk can split in the middle of a character or frame. TextDecoder owns byte carry, parseSseChunk holds the leftover decoded text, and the reducer only sees typed events.
Byte chunk A… 22 e2 82incomplete UTF-8 · decoder holds e2 82Byte chunk Bac 22 7d 0a 0a€ completes · frame delimiter arrives
  1. 1
    Byte chunks… e2 82 | ac …
  2. 2
    TextDecoderstream: true → decoded text
  3. 3
    Frame bufferremainder + chunk → blank line
  4. 4
    Typed eventtoken · { delta: ‘€’ }
  5. 5
    Reducerappend delta → render buffer
Decoded frameevent: token data: {"delta":"€"} Practice functionparseSseChunk(textRemainder, decodedText)
Cancel AbortSignal stops reader → parser → generator and ignores late events.Render pacing groups typed deltas into fewer UI updates; it never fixes broken byte or frame boundaries.

Keep request control separate from rendering. AbortSignal must stop the reader, parser, and generator at the adapter boundary. Render buffering is different: it can group several decoded token events into one React update, but it can't change their order or let generation keep running after cancellation.

Knowledge check

Why should bytes go through a streaming TextDecoder before you parse SSE frames?

Implementation

backend/streaming-transport.py
0 of 2 exercises verifiedOpen coding workspace →

Turn one typed event into the event-stream wire format.

Signature
def encode_sse(event, data):
Inputs
event non-empty str without CR/LF, data JSON-serializable value
Returns
str containing one complete SSE frame
Rule
write `event:`, compact JSON `data:`, and terminate the frame with a blank line
Example
token + {delta: "hi"} → `event: token\ndata: {"delta":"hi"}\n\n`
SSE encoder progressive practice rounds
Restoring saved code…
Reference solution

Approach Turn one typed event into the event-stream wire format.

import json def encode_sse(event, data):    if not isinstance(event, str) or not event or "\r" in event or "\n" in event:        raise ValueError("event name must be non-empty and contain no CR or LF")    serialized = json.dumps(data, separators=(",", ":"), ensure_ascii=False)    return f"event: {event}\ndata: {serialized}\n\n"

Build framing and step-by-step parsing in Python using decoded text chunks. A streaming decoder has already turned the byte chunks into strings and saved any incomplete UTF-8 bytes.

Saved results

Results created after your saved code passes its checks

The replay is course data. The validation result is tied to the code you saved and checked.

Loading…