diff --git a/internal/support/web/sse.go b/internal/support/web/sse.go index 236bcda3..747d939c 100644 --- a/internal/support/web/sse.go +++ b/internal/support/web/sse.go @@ -2,26 +2,27 @@ package support_web import ( "bytes" + "compress/gzip" "context" "encoding/json" "fmt" + "io" + "strings" "net/http" ) type SSEWriter struct { + w io.Writer f http.Flusher - w http.ResponseWriter } type HasId interface { MessageId() int64 } -func NewSSEWriter(ctx context.Context, w http.ResponseWriter) (*SSEWriter, error) { - f, ok := w.(http.Flusher) - - if !ok { +func NewSSEWriter(ctx context.Context, w http.ResponseWriter, r *http.Request) (*SSEWriter, error) { + if _, ok := w.(http.Flusher); !ok { return nil, http.ErrNotSupported } @@ -31,9 +32,15 @@ func NewSSEWriter(ctx context.Context, w http.ResponseWriter) (*SSEWriter, error w.Header().Set("Connection", "keep-alive") w.Header().Set("X-Accel-Buffering", "no") + var writer io.Writer = w + if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + w.Header().Set("Content-Encoding", "gzip") + writer = gzip.NewWriter(w) + } + sse := &SSEWriter{ - f: f, - w: w, + w: writer, + f: w.(http.Flusher), } return sse, nil @@ -50,6 +57,13 @@ func (s *SSEWriter) Write(data []byte) (int, error) { return written, err } + if f, ok := s.w.(*gzip.Writer); ok { + err := f.Flush() + if err != nil { + return written, err + } + } + s.f.Flush() return written, nil @@ -60,6 +74,14 @@ func (s *SSEWriter) Ping() error { return err } +func (s *SSEWriter) Close() error { + if s.w != nil { + return s.w.(io.Closer).Close() + } + + return nil +} + func (s *SSEWriter) Message(data any) error { encoded, err := json.Marshal(data) diff --git a/internal/web/events.go b/internal/web/events.go index 6f0754a6..c453f08a 100644 --- a/internal/web/events.go +++ b/internal/web/events.go @@ -13,7 +13,9 @@ import ( ) func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) { - sseWriter, err := support_web.NewSSEWriter(r.Context(), w) + sseWriter, err := support_web.NewSSEWriter(r.Context(), w, r) + defer sseWriter.Close() + if err != nil { log.Error().Err(err).Msg("error creating sse writer") http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/internal/web/logs.go b/internal/web/logs.go index eb0e735c..70b34148 100644 --- a/internal/web/logs.go +++ b/internal/web/logs.go @@ -245,7 +245,8 @@ func (h *handler) streamLogsForContainers(w http.ResponseWriter, r *http.Request return } - sseWriter, err := support_web.NewSSEWriter(r.Context(), w) + sseWriter, err := support_web.NewSSEWriter(r.Context(), w, r) + defer sseWriter.Close() if err != nil { log.Error().Err(err).Msg("error creating sse writer") http.Error(w, err.Error(), http.StatusInternalServerError)