45 lines
1.1 KiB
Go
45 lines
1.1 KiB
Go
package infra
|
|
|
|
import "net/http"
|
|
|
|
// SSEHandler retorna un http.HandlerFunc que setea los headers SSE,
|
|
// consume eventos del canal y los envia con flush. Cierra limpiamente
|
|
// si el cliente se desconecta (context cancelado) o si el canal se cierra.
|
|
//
|
|
// Headers seteados:
|
|
// Content-Type: text/event-stream
|
|
// Cache-Control: no-cache
|
|
// Connection: keep-alive
|
|
// X-Accel-Buffering: no (deshabilita buffering en nginx)
|
|
func SSEHandler(events <-chan SSEEvent) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
flusher, ok := w.(http.Flusher)
|
|
if !ok {
|
|
http.Error(w, "streaming unsupported", 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")
|
|
w.WriteHeader(http.StatusOK)
|
|
flusher.Flush()
|
|
|
|
ctx := r.Context()
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case ev, ok := <-events:
|
|
if !ok {
|
|
return
|
|
}
|
|
if err := SSESend(w, ev); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|