54 lines
1.2 KiB
Go
54 lines
1.2 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/local-mcp/local-mcp-go/internal/events"
|
|
)
|
|
|
|
// handleSSE streams server-sent events to browser clients.
|
|
func handleSSE(broker *events.Broker) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
// Set SSE headers
|
|
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")
|
|
|
|
flusher, ok := w.(http.Flusher)
|
|
if !ok {
|
|
writeError(w, http.StatusInternalServerError, "Streaming not supported")
|
|
return
|
|
}
|
|
|
|
// Subscribe to event broker
|
|
ch := broker.Subscribe()
|
|
defer broker.Unsubscribe(ch)
|
|
heartbeat := time.NewTicker(15 * time.Second)
|
|
defer heartbeat.Stop()
|
|
|
|
// Send initial connection event
|
|
w.Write([]byte("data: {\"type\":\"connected\"}\n\n"))
|
|
flusher.Flush()
|
|
|
|
// Stream events until client disconnects
|
|
for {
|
|
select {
|
|
case msg, ok := <-ch:
|
|
if !ok {
|
|
return // broker closed
|
|
}
|
|
w.Write(msg)
|
|
flusher.Flush()
|
|
case <-heartbeat.C:
|
|
w.Write([]byte(": keepalive\n\n"))
|
|
flusher.Flush()
|
|
case <-r.Context().Done():
|
|
return // client disconnected
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|