From 453bd09173ecfa8adb2a81da0f85c4516c196afa Mon Sep 17 00:00:00 2001 From: Thomas <27960254+thomiceli@users.noreply.github.com> Date: Sat, 27 Jun 2026 01:41:30 +0700 Subject: [PATCH] Better handler for committed http responses (#734) --- internal/web/handlers/gist/download.go | 6 ++-- internal/web/server/middlewares.go | 50 +++++++++++++------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/internal/web/handlers/gist/download.go b/internal/web/handlers/gist/download.go index 5f99bbf..3370ba3 100644 --- a/internal/web/handlers/gist/download.go +++ b/internal/web/handlers/gist/download.go @@ -101,9 +101,7 @@ func DownloadZip(ctx *context.Context) error { ctx.Response().Header().Set("Content-Type", "application/zip") ctx.Response().Header().Set("Content-Disposition", "attachment; filename="+gist.Identifier()+".zip") ctx.Response().Header().Set("Content-Length", strconv.Itoa(len(zipFile.Bytes()))) - _, err = ctx.Response().Write(zipFile.Bytes()) - if err != nil { - return ctx.ErrorRes(500, "Error writing the zip archive", err) - } + + _, _ = ctx.Response().Write(zipFile.Bytes()) return nil } diff --git a/internal/web/server/middlewares.go b/internal/web/server/middlewares.go index f3de826..c7ac564 100644 --- a/internal/web/server/middlewares.go +++ b/internal/web/server/middlewares.go @@ -93,44 +93,44 @@ func (s *Server) registerMiddlewares() { } func (s *Server) errorHandler(err error, ctx echo.Context) { + data, _ := ctx.Request().Context().Value(context.DataKeyStr).(echo.Map) + if data == nil { + data = echo.Map{} + } + var httpErr *context.HTTPError - data := ctx.Request().Context().Value(context.DataKeyStr).(echo.Map) if errors.As(err, &httpErr) { - acceptJson := strings.Contains(ctx.Request().Header.Get("Accept"), "application/json") data["error"] = err - if acceptJson || data["err_render"] == "json" { - if err := ctx.JSON(httpErr.Code, httpErr); err != nil { - if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) { - return - } - log.Fatal().Err(err).Send() - } + } else { + if isClientGone(err) { return } + log.Error().Err(err).Send() + httpErr = &context.HTTPError{Message: err.Error(), Code: http.StatusInternalServerError} + data["error"] = httpErr + } - if err := ctx.Render(httpErr.Code, "error", data); err != nil { - if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) { - return - } - log.Fatal().Err(err).Send() - } + if ctx.Response().Committed { return } - if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) { - return + acceptJson := strings.Contains(ctx.Request().Header.Get("Accept"), "application/json") + var renderErr error + if acceptJson || data["err_render"] == "json" { + renderErr = ctx.JSON(httpErr.Code, httpErr) + } else { + renderErr = ctx.Render(httpErr.Code, "error", data) } - log.Error().Err(err).Send() - httpErr = &context.HTTPError{Message: err.Error(), Code: http.StatusInternalServerError} - data["error"] = httpErr - if err := ctx.Render(500, "error", data); err != nil { - if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) { - return - } - log.Fatal().Err(err).Send() + + if renderErr != nil && !isClientGone(renderErr) { + log.Error().Err(renderErr).Send() } } +func isClientGone(err error) bool { + return errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) +} + func dataInit(next Handler) Handler { return func(ctx *context.Context) error { ctx.SetData("loadStartTime", time.Now())