Skip to content

fix(middleware): restore previous response writer in BodyDump - #3174

Open
rajpreetcodes wants to merge 1 commit into
labstack:masterfrom
rajpreetcodes:fix/body-dump-restore-response
Open

rajpreetcodes wants to merge 1 commit into
labstack:masterfrom
rajpreetcodes:fix/body-dump-restore-response

Conversation

@rajpreetcodes

@rajpreetcodes rajpreetcodes commented Oct 14, 2026 •

Copy link
Copy Markdown

What this PR does

Fixes #3173: middleware.BodyDump installs a wrapper bodyDumpResponseWriter on Context via c.SetResponse, but never restores the previous response writer before returning.

Because Echo.serveHTTP executes HTTPErrorHandler after the middleware chain unwinds, any error formatted by the error handler writes into the still-installed wrapper response writer. At that point, the underlying dump buffer (resBuf) has already been handed back to bodyDumpBufferPool via defer bodyDumpBufferPool.Put(resBuf). This creates a data race on bytes.Buffer under concurrent traffic and risks corrupting pooled request/response buffers.

Solution

  1. Capture origResponse := c.Response() before setting the wrapper.
  2. Defer restoring c.SetResponse(origResponse) so the previous response writer is restored whenever the middleware returns (normally, on error, or on panic).
  3. Because deferred calls execute LIFO, c.SetResponse(origResponse) runs before bodyDumpBufferPool.Put(resBuf), guaranteeing that c.Response() is restored before the buffer is returned to the pool and before HTTPErrorHandler writes.

Changes

  • middleware/body_dump.go: save and defer restoring previous response writer.
  • middleware/body_dump_test.go:
    • TestBodyDump_RestoreResponse: asserts that c.Response() is restored to its original value after BodyDump completes.
    • TestBodyDump_ErrorHandlerRace: exercises concurrent error handling under BodyDump with multiple goroutines.

Verification

  • go test ./...: all packages pass (github.com/labstack/echo/v5, echotest, middleware).
  • go test -v -run TestBodyDump_RestoreResponse ./middleware: confirmed failure on pre-fix code (expected: *echo.Response, actual: *middleware.bodyDumpResponseWriter), passes cleanly with fix.
  • Code formatted with gofmt -s.

BodyDump installs a wrapped bodyDumpResponseWriter on the Echo Context via c.SetResponse, but previously never restored the original writer when the middleware returned. Because Echo invokes HTTPErrorHandler after the middleware chain has unwound, subsequent error handler writes went through the wrapped writer into a buffer that had already been returned to bodyDumpBufferPool, creating a data race and potential body corruption under concurrent load.

Defer restoring the original response writer so that c.Response is reset before the pooled buffer is returned and before downstream error handling runs. Add regression tests verifying response writer restoration and concurrent error handling.

Fixes labstack#3173
@rajpreetcodes

Copy link
Copy Markdown
Author

@vishr This PR implements the fix proposed in #3173 by deferring c.SetResponse(origResponse), restoring the original response writer before BodyDump returns and before the global HTTPErrorHandler writes. Unit and concurrent data race test suites are included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

middleware.BodyDump: data race — error response is written into a dump buffer already returned to sync.Pool

1 participant