Skip to content

fix(gateway): buffer response headers to prevent superfluous WriteHeader#35

Merged
olamide226 merged 1 commit intomainfrom
fix/gateway-superfluous-writeheader
Mar 16, 2026
Merged

fix(gateway): buffer response headers to prevent superfluous WriteHeader#35
olamide226 merged 1 commit intomainfrom
fix/gateway-superfluous-writeheader

Conversation

@olamide226
Copy link
Copy Markdown
Contributor

@olamide226 olamide226 commented Mar 16, 2026

Summary

  • Root cause: The inject middleware's responseRecorder delegated Header() to the real ResponseWriter, so upstream handlers (e.g. httputil.ReverseProxy) wrote headers directly to the client. When Flush() was called, headers were prematurely committed, causing superfluous response.WriteHeader warnings on the subsequent writeback.
  • Fix: The recorder now owns a separate http.Header map. Upstream headers are buffered there, then copied back to the real writer via copyHeaders() only when the middleware is ready to commit. Flush() is a no-op to prevent premature commitment.
  • Adds .gocache/ to .gitignore

Test plan

  • go test -race ./internal/inject/ passes
  • Verify superfluous response.WriteHeader warning no longer appears in gateway logs
  • Verify HTML injection still works in proxy mode
  • Verify non-HTML responses (JS, CSS, JSON) pass through with correct headers

The inject middleware's responseRecorder was letting upstream handlers
write headers directly to the real ResponseWriter. When httputil.ReverseProxy
called Flush(), this prematurely committed headers and caused a second
WriteHeader call when the middleware later wrote its own status code.

Fix by giving the recorder its own http.Header map so upstream headers are
buffered until the middleware is ready to write back. Flush() is now a no-op
since the middleware must buffer the full response before deciding whether
to inject. Headers are copied back via copyHeaders() before WriteHeader.
Copilot AI review requested due to automatic review settings March 16, 2026 19:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a header-commit ordering issue in the gateway’s HTML injection middleware by buffering response headers (instead of delegating directly to the underlying ResponseWriter), preventing upstream handlers from committing headers early and triggering superfluous response.WriteHeader warnings.

Changes:

  • Make responseRecorder own its own http.Header map and delay copying headers to the real writer until writeback time.
  • Make responseRecorder.Flush() a no-op to prevent premature header/body commitment.
  • Add tests covering upstream Flush() behavior and header buffering behavior; add .gocache/ to .gitignore.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
gateway/internal/inject/inject.go Buffers headers in the recorder and copies them to the real writer only when committing the final response.
gateway/internal/inject/inject_test.go Adds regression tests ensuring upstream flush doesn’t commit early and that headers are preserved through buffering.
.gitignore Ignores .gocache/ directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@olamide226 olamide226 merged commit f82cd95 into main Mar 16, 2026
13 checks passed
@olamide226 olamide226 deleted the fix/gateway-superfluous-writeheader branch March 16, 2026 20:22
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.

2 participants