From ae11d4aa0160849dc8c5388638fa70281892d053 Mon Sep 17 00:00:00 2001 From: Ryan McGuire Date: Sun, 24 Aug 2025 11:50:03 -0400 Subject: [PATCH] refactor: refine HTTP response body logging, explicitly handling 204 No Content, and improving error management for body reads --- pkg/srv/http/http_log.go | 46 ++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/pkg/srv/http/http_log.go b/pkg/srv/http/http_log.go index 4304a36..cb05005 100644 --- a/pkg/srv/http/http_log.go +++ b/pkg/srv/http/http_log.go @@ -3,7 +3,8 @@ package http import ( "bytes" "context" - "errors" + "fmt" + "io" "net/http" "regexp" "time" @@ -41,25 +42,38 @@ func loggingMiddleware(appCtx context.Context, next http.Handler) http.Handler { Dur("duration", time.Since(start)). Msg("http request served") - // Log response with body if not 204 - if lrr.statusCode != http.StatusNoContent { + // Log response with body if not 204 + if lrr.statusCode == http.StatusNoContent { trcLog := log.Trace(). Str("path", r.URL.Path). Int("statusCode", lrr.statusCode) - firstByte, err := lrr.body.ReadByte() - if err != nil { - trcLog.Err(errors.New("invalid response body")).Send() - return - } - lrr.body.UnreadByte() - - if firstByte == '{' { - trcLog = trcLog.RawJSON("response", lrr.body.Bytes()) - } else { - trcLog = trcLog.Bytes("response", lrr.body.Bytes()) - } - trcLog.Msg("http response") + trcLog.Msg("http response (no content)") // Explicitly log 204 + return // No body to log for 204 No Content } + + trcLog := log.Trace(). + Str("path", r.URL.Path). + Int("statusCode", lrr.statusCode) + + firstByte, err := lrr.body.ReadByte() + if err != nil { + if err == io.EOF { + // Body is empty, which might be valid for some non-204 responses. + trcLog.Msg("http response (empty body)") + } else { + // Other error reading the body. Wrap the original error for context. + trcLog.Err(fmt.Errorf("error reading response body: %w", err)).Send() + } + return // No further body processing if there was an error or it was empty + } + lrr.body.UnreadByte() // Put the byte back for Bytes() to read + + if firstByte == '{' { + trcLog = trcLog.RawJSON("response", lrr.body.Bytes()) + } else { + trcLog = trcLog.Bytes("response", lrr.body.Bytes()) + } + trcLog.Msg("http response") }) }