package main import ( "encoding/json" "fmt" "log/slog" "net/http" ) func sseHandler(broker *Broker) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "streaming not supported", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") w.Header().Set("X-Accel-Buffering", "no") // disable nginx buffering ch := broker.Subscribe() defer broker.Unsubscribe(ch) slog.Debug("SSE client connected") ctx := r.Context() for { select { case <-ctx.Done(): slog.Debug("SSE client disconnected") return case evt, ok := <-ch: if !ok { // Broker shut down return } writeSSEEvent(w, flusher, "push", evt) } } } } func writeSSEEvent(w http.ResponseWriter, flusher http.Flusher, eventType string, data any) { jsonData, err := json.Marshal(data) if err != nil { slog.Warn("failed to marshal SSE event", "error", err) return } _, err = fmt.Fprintf(w, "event: %s\ndata: %s\n\n", eventType, jsonData) if err != nil { slog.Debug("failed to write SSE event, client likely disconnected", "error", err) return } flusher.Flush() }