package infra import ( "fmt" "net/http" "strings" ) // SSESend escribe un evento SSE formateado al ResponseWriter y hace flush si es posible. // Sigue la spec W3C: campos opcionales (event, id, retry) solo se incluyen si tienen valor. // Data con saltos de linea se traduce a multiples lineas "data:" segun la spec. // Retorna error si la escritura falla. func SSESend(w http.ResponseWriter, event SSEEvent) error { var b strings.Builder if event.Event != "" { b.WriteString("event: ") b.WriteString(event.Event) b.WriteByte('\n') } if event.ID != "" { b.WriteString("id: ") b.WriteString(event.ID) b.WriteByte('\n') } if event.Retry > 0 { fmt.Fprintf(&b, "retry: %d\n", event.Retry) } // Data: cada salto de linea genera una nueva linea "data:" for _, line := range strings.Split(event.Data, "\n") { b.WriteString("data: ") b.WriteString(line) b.WriteByte('\n') } b.WriteByte('\n') // separador de eventos if _, err := w.Write([]byte(b.String())); err != nil { return fmt.Errorf("sse send: %w", err) } if flusher, ok := w.(http.Flusher); ok { flusher.Flush() } return nil }