sse-clients.md

reference

← Back to skill

Content hash: 6bf6c1400b3df972dcb106ad3af989ecc50f083f70523d2239a130407b5f21f0
## SSE Client Patterns

### Browser: EventSource (GET only)
```javascript
const es = new EventSource('/chat?messages=hello');
es.addEventListener('delta', (e) => {
    const { delta } = JSON.parse(e.data);
    outputEl.textContent += delta;
});
es.addEventListener('done', (e) => {
    console.log('Stream complete');
    es.close();
});
es.addEventListener('error', (e) => {
    console.error('Stream error');
    es.close();
});
```

### Browser: fetch with streaming (POST)
```javascript
const response = await fetch('/chat', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ messages: 'hello' }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    // Parse SSE events from buffer
    const lines = buffer.split('\n\n');
    buffer = lines.pop(); // incomplete event stays in buffer
    for (const line of lines) {
        if (line.startsWith('event: delta')) { /* handle */ }
        if (line.startsWith('event: done')) { /* handle */ }
    }
}
```

### Python client
```python
import aiohttp, json

async with aiohttp.ClientSession() as session:
    async with session.post(
        'http://localhost:8000/chat',
        json={'messages': 'hello'}
    ) as resp:
        async for line in resp.content:
            text = line.decode().strip()
            if text.startswith('data:'):
                data = json.loads(text[5:])
                print(data.get('delta', ''), end='', flush=True)
```

### Nginx reverse proxy config
```nginx
location /chat {
    proxy_pass http://backend:8000;
    proxy_buffering off;            # CRITICAL: don't buffer SSE
    proxy_cache off;
    proxy_set_header X-Accel-Buffering no;
    proxy_read_timeout 300s;
    chunked_transfer_encoding on;
}
```

### Key metrics to track
- **TTFT** (time-to-first-token): first user-visible token
- **Tokens/sec**: sustained streaming speed
- **Cancellation rate**: % of streams abandoned mid-response