From 31d806e09535b627bf9f255dc12c222aaa5bd3df Mon Sep 17 00:00:00 2001 From: toim Date: Tue, 31 Mar 2026 14:59:12 +0300 Subject: [PATCH] fix SSE example disconnecting after 30 sec by disabling write timeout as this connection is long-lived --- cookbook/sse/broadcast/server.go | 19 ++++++++++++++++--- cookbook/sse/simple/server.go | 24 ++++++++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/cookbook/sse/broadcast/server.go b/cookbook/sse/broadcast/server.go index e83da9df..a54e00ec 100644 --- a/cookbook/sse/broadcast/server.go +++ b/cookbook/sse/broadcast/server.go @@ -1,8 +1,11 @@ package main import ( - "errors" + "context" "net/http" + "os" + "os/signal" + "syscall" "time" "github.com/labstack/echo/v5" @@ -49,7 +52,17 @@ func main() { return nil }) - if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) { - e.Logger.Error("shutting down the server", "error", err) + sc := echo.StartConfig{ + Address: ":8080", + BeforeServeFunc: func(s *http.Server) error { + s.WriteTimeout = 0 // IMPORTANT: disable for SSE + return nil + }, + } + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) // start shutdown process on ctrl+c + defer cancel() + + if err := sc.Start(ctx, e); err != nil { + e.Logger.Error("failed to start server", "error", err) } } diff --git a/cookbook/sse/simple/server.go b/cookbook/sse/simple/server.go index f51cac38..4e0b9bdb 100644 --- a/cookbook/sse/simple/server.go +++ b/cookbook/sse/simple/server.go @@ -1,9 +1,13 @@ package main import ( - "errors" + "context" + "fmt" "log" "net/http" + "os" + "os/signal" + "syscall" "time" "github.com/labstack/echo/v5" @@ -27,14 +31,16 @@ func main() { ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() + count := uint64(0) for { select { case <-c.Request().Context().Done(): log.Printf("SSE client disconnected, ip: %v", c.RealIP()) return nil case <-ticker.C: + count++ event := Event{ - Data: []byte("time: " + time.Now().Format(time.RFC3339Nano)), + Data: []byte(fmt.Sprintf("count: %d, time: %s\n\n", count, time.Now().Format(time.RFC3339Nano))), } if err := event.MarshalTo(w); err != nil { return err @@ -46,7 +52,17 @@ func main() { } }) - if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Fatal(err) + sc := echo.StartConfig{ + Address: ":8080", + BeforeServeFunc: func(s *http.Server) error { + s.WriteTimeout = 0 // IMPORTANT: disable for SSE + return nil + }, + } + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) // start shutdown process on ctrl+c + defer cancel() + + if err := sc.Start(ctx, e); err != nil { + e.Logger.Error("failed to start server", "error", err) } }