fix: Plug middleware to respect Response writer swaps#451
Conversation
Bug 1 (mux.go): Kit.Plug bridge called next.ServeHTTP(w, r) with the captured outer writer, ignoring any ctx.Response swap made by the plug (e.g. Logger replacing the writer with a ResponseRecorder). Fix: use c.Response and c.Request so the downstream chi handler receives the swapped writer. Bug 2 (recorder.go): ResponseRecorder.Write did not default Status to 200 when called without a prior WriteHeader, unlike net/http. Fix: set Status = 200 on the first Write when Status is still 0. Adds regression tests for both bugs. https://claude.ai/code/session_01SYHXLF9NZsd9AvunJ6az8v
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Review summary
Clean, minimal bug fix with a clear root cause. The one-line change to Critical issues 🔴None Warnings 🟡1. New recorder tests missing
func TestResponseRecorder_Write_DefaultsStatusTo200(t *testing.T) {
t.Parallel()
// ...
}2. Response written to swapped writer is lost from the real client connection In the regression test the plug fully replaces recorder := httputil.NewResponseRecorder(ctx.Response) // wraps real writer, not replaces
ctx.Response = recorder
err := next(ctx)
// inspect recorder.Status / recorder.BodyThe existing Suggestions 🟢1. The
Status int // 0 until WriteHeader or Write is called2. Comment in regression test references PR/fix context // Regression: Plug used to call next.ServeHTTP(w, r) with the captured outer
// writer, discarding any ctx.Response swap made by the plug (e.g. a recorder).Per the project convention, comments should not reference the specific fix or issue number — those belong in commit/PR history. The test name already conveys the intent; the comment could be shortened to just document the invariant being asserted. Generated with Claude Code |
Summary
Fixed a bug in the
Plugmiddleware system where response writer swaps made by plugs (e.g., wrapping with a recorder) were being discarded when calling the next handler. The middleware now correctly passes the potentially-modifiedctx.Responseto downstream handlers instead of always using the original outer writer.Key Changes
Plugto callnext.ServeHTTP(c.Response, c.Request)instead ofnext.ServeHTTP(w, r), ensuring that any response writer modifications made by the plug are visible to downstream handlersWrite()method to mirror standardnet/httpbehavior whenWriteHeaderhasn't been explicitly calledImplementation Details
The core issue was that the plug middleware was capturing the outer response writer
win a closure and always passing it to the next handler, ignoring anyctx.Responsemodifications. By passingc.Responseinstead, plugs can now effectively wrap or replace the response writer for the entire handler chain. The recorder status defaulting ensures compatibility with standard HTTP handler behavior.https://claude.ai/code/session_01SYHXLF9NZsd9AvunJ6az8v