Skip to content

fix(middleware): pass through http.Flusher for SSE streaming#52

Merged
hallelx2 merged 1 commit into
mainfrom
halleluyaholudele/sse-flusher-middleware
Jul 3, 2026
Merged

fix(middleware): pass through http.Flusher for SSE streaming#52
hallelx2 merged 1 commit into
mainfrom
halleluyaholudele/sse-flusher-middleware

Conversation

@hallelx2

@hallelx2 hallelx2 commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Streaming endpoints (/v1/answer/treewalk?stream=true, /v1/query/stream) failed with "response writer does not support http.Flusher": the logging/metrics/tracing middlewares wrap the ResponseWriter to capture status+bytes but none forwarded Flush(). Added Flush() (delegating to the wrapped writer) + Unwrap() to all three recorders so flushes propagate through the chain. Unblocks the observable streaming Playground.

Summary by CodeRabbit

  • New Features
    • Improved support for streaming responses, including Server-Sent Events, through middleware layers.
    • Response wrappers now better integrate with response-controller behavior by exposing the underlying response writer when needed.

The request-logging, metrics, and tracing middlewares each wrap the
ResponseWriter to capture status/bytes, but none implemented
http.Flusher. Streaming handlers (/v1/answer/treewalk?stream=true,
/v1/query/stream) do w.(http.Flusher) and errored with 'response
writer does not support http.Flusher'. Add Flush() (delegating to the
wrapped writer) + Unwrap() to statusRecorder, metricsRecorder, and
tracingRecorder so flushes propagate through the whole chain and SSE
streams in real time.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @hallelx2, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Three middleware ResponseWriter wrapper types—statusRecorder, metricsRecorder, and tracingRecorder—each gain a Flush() method that delegates to the underlying http.Flusher when supported, and an Unwrap() method returning the wrapped http.ResponseWriter for http.ResponseController use.

Changes

Middleware ResponseWriter streaming compatibility

Layer / File(s) Summary
Add Flush and Unwrap methods to recorders
internal/middleware/logging.go, internal/middleware/metrics.go, internal/middleware/tracing.go
Each wrapper type (statusRecorder, metricsRecorder, tracingRecorder) adds a Flush() method that forwards to the underlying http.Flusher if present, and an Unwrap() method returning the wrapped http.ResponseWriter.

Estimated code review effort: 1 (Trivial) | ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: forwarding http.Flusher through middleware for SSE streaming.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch halleluyaholudele/sse-flusher-middleware

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/middleware/tracing.go (1)

70-80: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correct fix; consider consolidating duplicated Flush/Unwrap logic.

The Flush()/Unwrap() bodies here are identical to the ones just added in statusRecorder (logging.go) and metricsRecorder (metrics.go). Since all three live in the middleware package, consider factoring the common logic into a small embeddable helper (e.g., a flusher struct wrapping http.ResponseWriter) to avoid triplicated boilerplate going forward.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/middleware/tracing.go` around lines 70 - 80, The Flush and Unwrap
implementations in tracingRecorder duplicate the same response-writer
passthrough logic already added in statusRecorder and metricsRecorder. Refactor
this shared behavior into a small reusable helper in the middleware package (for
example, an embeddable wrapper around http.ResponseWriter that provides Flush
and Unwrap), then have tracingRecorder, statusRecorder, and metricsRecorder
reuse it instead of keeping three copies.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/middleware/tracing.go`:
- Around line 70-80: The Flush and Unwrap implementations in tracingRecorder
duplicate the same response-writer passthrough logic already added in
statusRecorder and metricsRecorder. Refactor this shared behavior into a small
reusable helper in the middleware package (for example, an embeddable wrapper
around http.ResponseWriter that provides Flush and Unwrap), then have
tracingRecorder, statusRecorder, and metricsRecorder reuse it instead of keeping
three copies.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91adfbc2-9405-4ce6-9618-c08db50d0edc

📥 Commits

Reviewing files that changed from the base of the PR and between 6a0d1d4 and 44b868d.

📒 Files selected for processing (3)
  • internal/middleware/logging.go
  • internal/middleware/metrics.go
  • internal/middleware/tracing.go

@hallelx2 hallelx2 merged commit 8d074fa into main Jul 3, 2026
8 checks passed
@hallelx2 hallelx2 deleted the halleluyaholudele/sse-flusher-middleware branch July 3, 2026 18:02
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.

1 participant