Skip to content

🐛 fix: Add BodyStream() logic to adaptor.FiberHandler middleware#3799

Merged
ReneWerner87 merged 17 commits intogofiber:mainfrom
grivera64:refactor(adaptor)/fiber-handler-stream-writer-support
Oct 22, 2025
Merged

🐛 fix: Add BodyStream() logic to adaptor.FiberHandler middleware#3799
ReneWerner87 merged 17 commits intogofiber:mainfrom
grivera64:refactor(adaptor)/fiber-handler-stream-writer-support

Conversation

@grivera64
Copy link
Member

@grivera64 grivera64 commented Oct 10, 2025

Description

In the opposite direction of #3421, there is also a bug where adaptor.FiberHandler also does not support buffered streaming directly to a net/http handler.

This PR adds BodyStream() logic to ensure that c.SendStreamWriter() works as expected.

Fixes #3798

Changes introduced

List the new features or adjustments introduced in this pull request. Provide details on benchmarks, documentation updates, changelog entries, and if applicable, the migration guide.

  • Benchmarks: Describe any performance benchmarks and improvements related to the changes.
  • Documentation Update: Detail the updates made to the documentation and links to the changed files.
  • Changelog/What's New: Include a summary of the additions for the upcoming release notes.
    • Buffered streaming support for Fiber -> net/http handlers
  • Migration Guide: If necessary, provide a guide or steps for users to migrate their existing code to accommodate these changes.
  • API Alignment with Express: Explain how the changes align with the Express API.
  • API Longevity: Discuss the steps taken to ensure that the new or updated APIs are consistent and not prone to breaking changes.
  • Examples: Provide examples demonstrating the new features or changes in action.

Type of change

Please delete options that are not relevant.

  • Enhancement (improvement to existing features and functionality)
    • Buffered Streaming Support when converting from Fiber -> net/http
  • Documentation update (changes to documentation)

Checklist

Before you submit your pull request, please make sure you meet these requirements:

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

Important

This PR is a DRAFT. The following functionality is a WIP:

  • [X] Add BodyStream() logic
  • [x] Add unit tests

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds streaming support to the HTTP→Fiber adaptor: when a response exposes a BodyStream it streams in 32 KiB pooled buffers, writing chunks to the net/http ResponseWriter and flushing after each chunk; otherwise it writes the full body. Tests added for flush and interrupted streaming.

Changes

Cohort / File(s) Summary
Adaptor streaming implementation
middleware/adaptor/adaptor.go
Adds chunked streaming when BodyStream is present: defines bufferSize (32 KiB) and a sync.Pool of *[bufferSize]byte buffers, reads from BodyStream into pooled buffers, writes chunks to http.ResponseWriter, flushes via http.Flusher, falls back to writing full body if no stream, and panics on unexpected pooled buffer type.
Streaming tests and flusher stub
middleware/adaptor/adaptor_test.go
Adds a no-op Flush() to netHTTPResponseWriter, imports bufio, and adds Test_FiberHandler_WithSendStreamWriter and Test_FiberHandler_WithInterruptedSendStreamWriter to validate streamed flush behavior and partial/interrupted stream handling under timeouts.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant NetHTTP as net/http Handler
  participant Adaptor as adaptor.FiberHandler
  participant Fiber as Fiber Handler
  participant BodyStream

  Client->>NetHTTP: HTTP request
  NetHTTP->>Adaptor: ServeHTTP(w,r)
  Adaptor->>Fiber: invoke Fiber handler
  alt BodyStream present
    Fiber-->>Adaptor: Response with BodyStream
    loop stream chunks
      Adaptor->>BodyStream: Read into pooled 32KiB buffer
      BodyStream-->>Adaptor: Chunk bytes
      Adaptor->>NetHTTP: Write chunk to ResponseWriter
      Adaptor->>NetHTTP: Flush (http.Flusher)
    end
  else No BodyStream
    Fiber-->>Adaptor: Response with full body
    Adaptor->>NetHTTP: Write full body once
  end
  NetHTTP-->>Client: HTTP response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

☢️ Bug

Suggested reviewers

  • gaby
  • sixcolors

Poem

I nibbled chunks with careful paws,
Pooled my buffers, kept my laws.
I flushed each nibble down the wire,
Teapot warmed and bytes aspire.
Hop—stream on, little rabbit choir 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "Add BodyStream() logic to adaptor.FiberHandler middleware" directly and clearly summarizes the main change in the changeset. The code modifications add streaming support with flushing to the adaptor by implementing BodyStream logic, exactly as stated in the title. The title is specific, concise, and accurately reflects the primary objective without vague terms.
Linked Issues Check ✅ Passed The code changes directly address the requirements of linked issue #3798: the modifications to middleware/adaptor/adaptor.go implement BodyStream logic that executes when a Fiber handler uses c.SendStreamWriter(), enabling buffered streaming with flushing to the net/http ResponseWriter via an http.Flusher. The addition of two tests (Test_FiberHandler_WithSendStreamWriter and Test_FiberHandler_WithInterruptedSendStreamWriter) validates the streaming behavior with proper flushing and partial sends under timeout conditions, fully satisfying the issue's core objectives.
Out of Scope Changes Check ✅ Passed All code changes are directly scoped to the objectives of linked issue #3798. The modifications to adaptor.go add the required BodyStream streaming logic with buffered pooling and flushing, while the test additions validate the implemented functionality. No unrelated changes such as unrelated refactoring, unrelated feature additions, or tangential modifications are present in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea93cdc and c973628.

📒 Files selected for processing (1)
  • middleware/adaptor/adaptor_test.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • middleware/adaptor/adaptor_test.go

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 and usage tips.

@codecov
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

❌ Patch coverage is 84.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.91%. Comparing base (b00805c) to head (e4f688e).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
middleware/adaptor/adaptor.go 84.00% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3799   +/-   ##
=======================================
  Coverage   91.90%   91.91%           
=======================================
  Files         115      115           
  Lines       12353    12377   +24     
=======================================
+ Hits        11353    11376   +23     
  Misses        729      729           
- Partials      271      272    +1     
Flag Coverage Δ
unittests 91.91% <84.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gaby gaby requested a review from Copilot October 10, 2025 11:10
@gaby
Copy link
Member

gaby commented Oct 10, 2025

/gemini review

@gaby gaby added this to v3 Oct 10, 2025
@gaby gaby added this to the v3 milestone Oct 10, 2025
Copy link
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 bug where adaptor.FiberHandler middleware didn't support buffered streaming to net/http handlers. The fix adds BodyStream() logic to enable proper streaming when converting Fiber responses to net/http handlers, ensuring that c.SendStreamWriter() works as expected.

  • Adds a new buffer pool for efficient stream processing
  • Implements streaming logic with chunked reading and flushing
  • Maintains backward compatibility for non-streaming responses

@gaby gaby changed the title 🩹 Fix: Add BodyStream() logic to adaptor.FiberHandler middleware 🐛 fix: Add BodyStream() logic to adaptor.FiberHandler middleware Oct 10, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces streaming support for adaptor.FiberHandler to correctly handle c.SendStreamWriter(). The implementation uses a sync.Pool for buffer management to stream the response body in chunks. My review includes a couple of suggestions to improve performance and robustness by refining the buffer pool implementation and ensuring resources are properly released.

@grivera64 grivera64 force-pushed the refactor(adaptor)/fiber-handler-stream-writer-support branch from a1389d5 to 4cf2916 Compare October 11, 2025 03:28
@grivera64 grivera64 force-pushed the refactor(adaptor)/fiber-handler-stream-writer-support branch from 36c8eb7 to d4622e7 Compare October 14, 2025 06:55
@grivera64
Copy link
Member Author

Note: Since Fiber's client doesn't fully support streaming yet, I used net/http's client instead for testing purposes. This should be okay to keep for testing, but we could later replace it with Fiber's client once #3711 is complete and merged.

@efectn efectn marked this pull request as ready for review October 14, 2025 12:33
@efectn efectn requested a review from a team as a code owner October 14, 2025 12:33
@efectn efectn marked this pull request as draft October 14, 2025 12:33
@gaby gaby requested a review from Copilot October 14, 2025 12:36
@gaby
Copy link
Member

gaby commented Oct 14, 2025

/gemini review

Copy link
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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

@gaby
Copy link
Member

gaby commented Oct 14, 2025

@grivera64 The 32 * 1024 value should probably be a constant or type. Its reference in multiple places which is prone to breaking in the future.

Also, why 32*1024 ? Isn't that quite small?

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces streaming support for Fiber to net/http handlers by implementing logic for BodyStream(). The changes are a good step forward, but I've identified a few areas for improvement regarding error handling and code maintainability. Specifically, I've pointed out a potential panic that could crash the server, an unhandled error that could lead to resource leaks, and some suggestions to improve code clarity in both the implementation and the new tests. Addressing these points will make the new functionality more robust and reliable.

@grivera64
Copy link
Member Author

@grivera64 The 32 * 1024 value should probably be a constant or type. Its reference in multiple places which is prone to breaking in the future.

Also, why 32*1024 ? Isn't that quite small?

For sure, I will add a const to refer to that size.

32 * 1024 is the default buffer size used by io.Copy here is 32 KiB. I didn't use io.Copy here though because it doesn't flush after writing to the destination writer.

It is a small default, but we can increase it if that would be better (e.g. 128 KiB).

@grivera64 grivera64 marked this pull request as ready for review October 14, 2025 18:11
@grivera64 grivera64 requested a review from Copilot October 14, 2025 18:13
Copy link
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

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

Comment on lines +280 to +282
if !ok {
panic(fmt.Errorf("failed to type-assert to *[%d]byte", bufferSize))
}
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

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

Using panic for a type assertion failure is inappropriate here. This should never happen with a properly configured sync.Pool, but if it does, it would crash the entire application. Consider logging an error and falling back to a regular write operation instead.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
middleware/adaptor/adaptor.go (1)

279-282: Replace panic with graceful error handling.

Using panic in a web handler can crash the server process if the pool returns an unexpected type, potentially causing a denial of service. This represents a programming error within the package that should be logged and handled gracefully instead of crashing.

Apply this diff to handle the error gracefully:

-	bufPtr, ok := bufferPool.Get().(*[bufferSize]byte)
-	if !ok {
-		panic(fmt.Errorf("failed to type-assert to *[%d]byte", bufferSize))
-	}
+	bufPtr, ok := bufferPool.Get().(*[bufferSize]byte)
+	if !ok {
+		http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
+		return
+	}

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a167c6f and a80c8f4.

📒 Files selected for processing (2)
  • middleware/adaptor/adaptor.go (2 hunks)
  • middleware/adaptor/adaptor_test.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (Make target: make format).
Run golangci-lint for linting (Make target: make lint).
Run go vet as part of audit to catch suspicious constructs (Make target: make audit).
Optimize struct field alignment with betteralign (Make target: make betteralign).
Apply gopls modernize to update code patterns (Make target: make modernize).

Files:

  • middleware/adaptor/adaptor_test.go
  • middleware/adaptor/adaptor.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Run the test suite with gotestsum (Make target: make test).
Run benchmarks with go test (Make target: make benchmark).

Files:

  • middleware/adaptor/adaptor_test.go
🧠 Learnings (1)
📚 Learning: 2025-05-08T08:14:37.302Z
Learnt from: mdelapenya
PR: gofiber/fiber#3434
File: app.go:623-636
Timestamp: 2025-05-08T08:14:37.302Z
Learning: In the gofiber/fiber framework, service startup failures should panic rather than allowing the application to continue running with degraded functionality, as this is the agreed-upon design decision.

Applied to files:

  • middleware/adaptor/adaptor.go
🧬 Code graph analysis (1)
middleware/adaptor/adaptor_test.go (2)
constants.go (3)
  • StatusTeapot (91-91)
  • MethodGet (5-5)
  • NetworkTCP4 (292-292)
middleware/adaptor/adaptor.go (1)
  • FiberHandlerFunc (161-163)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: repeated
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: Compare
🔇 Additional comments (3)
middleware/adaptor/adaptor.go (2)

32-38: LGTM! Buffer pool is well-designed.

The constant definition and array pointer pooling align with best practices. The 32 KiB buffer size matches Go's io.Copy default, which is a sensible choice for streaming operations.


286-298: LGTM! Streaming loop is well-implemented.

The loop properly handles read/write errors and flushes after each write, ensuring data is delivered to the client incrementally. The error handling addresses previous review feedback.

middleware/adaptor/adaptor_test.go (1)

510-510: LGTM! No-op Flush implementation is appropriate.

Adding a no-op Flush() method allows netHTTPResponseWriter to satisfy the http.Flusher interface for testing streaming behavior.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
middleware/adaptor/adaptor_test.go (1)

704-732: Consider reducing sleep duration for faster tests.

The 200ms sleep simulates a long operation, which is valid for testing the streaming pattern. However, if test suite performance becomes a concern, consider reducing this to 50-100ms—streaming behavior will still be validated.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a80c8f4 and 30560cb.

📒 Files selected for processing (1)
  • middleware/adaptor/adaptor_test.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (Make target: make format).
Run golangci-lint for linting (Make target: make lint).
Run go vet as part of audit to catch suspicious constructs (Make target: make audit).
Optimize struct field alignment with betteralign (Make target: make betteralign).
Apply gopls modernize to update code patterns (Make target: make modernize).

Files:

  • middleware/adaptor/adaptor_test.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Run the test suite with gotestsum (Make target: make test).
Run benchmarks with go test (Make target: make benchmark).

Files:

  • middleware/adaptor/adaptor_test.go
🧬 Code graph analysis (1)
middleware/adaptor/adaptor_test.go (2)
constants.go (3)
  • StatusTeapot (91-91)
  • MethodGet (5-5)
  • NetworkTCP4 (292-292)
middleware/adaptor/adaptor.go (1)
  • FiberHandlerFunc (161-163)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: Compare
  • GitHub Check: repeated
🔇 Additional comments (1)
middleware/adaptor/adaptor_test.go (1)

510-511: LGTM: Appropriate no-op for test mock.

The no-op Flush() implementation is correct for this test helper type. Note that Test_FiberHandler_WithSendStreamWriter uses this mock, so it validates the streaming logic path but not the actual flush-to-wire behavior. Test_FiberHandler_WithInterruptedSendStreamWriter addresses this by using a real HTTP server where flushing matters.

@gaby
Copy link
Member

gaby commented Oct 14, 2025

@grivera64 32kb is fine then. We can revisit in the future

@ReneWerner87 ReneWerner87 merged commit b02f39c into gofiber:main Oct 22, 2025
14 of 15 checks passed
@github-project-automation github-project-automation bot moved this to Done in v3 Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

🐛 [Bug]: FiberHandler adaptor does not flush when using SendStreamWriter

5 participants