Skip to content

swift-http-server: Use AsyncReader in RequestBody - #893

Open
adam-fowler wants to merge 9 commits into
swift-http-serverfrom
request-async-reader-v2
Open

swift-http-server: Use AsyncReader in RequestBody#893
adam-fowler wants to merge 9 commits into
swift-http-serverfrom
request-async-reader-v2

Conversation

@adam-fowler

@adam-fowler adam-fowler commented Sep 8, 2026

Copy link
Copy Markdown
Member

Replace AsyncSequence of ByteBuffers in RequestBody with a AsyncReader. As the AsyncReader is ~Copyable the easiest way to do this is make RequestBody a class.

Also replace all functionality that returned a ByteBuffer to return a UniqueArray.

for try await buffer in request.body {
    ...
}

becomes

request.body.forEachBuffer { buffer in
    ...
}

TODO:

  • Fix I/O on closed channel errors
  • Add support for consumeWithInboundCloseHandler
  • Add support for processing request data
  • Fix up FileIO

Streaming tests need a response writer, so will fix those later

@adam-fowler
adam-fowler requested a review from Joannis as a code owner September 8, 2026 08:28
Drain request body if it hasn't been consumed
Return iterator to RenderState on errors
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.06883% with 27 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (swift-http-server@2288808). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...s/HummingbirdCore/Request/RequestAsyncReader.swift 84.04% 15 Missing ⚠️
Sources/HummingbirdCore/Request/RequestBody.swift 87.50% 6 Missing ⚠️
Sources/HummingbirdCore/Utils/Disconnected.swift 66.66% 3 Missing ⚠️
Tests/HummingbirdTests/ApplicationTests.swift 83.33% 2 Missing ⚠️
Tests/HummingbirdCoreTests/CoreTests.swift 91.66% 1 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                  @@
##             swift-http-server     #893   +/-   ##
====================================================
  Coverage                     ?   89.39%           
====================================================
  Files                        ?      168           
  Lines                        ?    12781           
  Branches                     ?        0           
====================================================
  Hits                         ?    11426           
  Misses                       ?     1355           
  Partials                     ?        0           

☔ View full report in Codecov by Harness.
📢 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.

Comment thread Sources/Hummingbird/Codable/JSON/JSONCoding.swift

Copilot AI 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.

🟡 Changes recommended

Key streaming-related tests are currently disabled and HTTP/2 request draining behavior needs to be made robust to prevent regressions during the migration.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR migrates RequestBody from an AsyncSequence<ByteBuffer> model to an AsyncReader-based model (with UniqueArray<UInt8> buffers), updating server/channel handling and I/O utilities to match the new move-only reader semantics.

Changes:

  • Replaces request-body streaming from AsyncSequence<ByteBuffer> to RequestAsyncReader (UniqueArray<UInt8> buffers), making RequestBody a reference type to support ~Copyable.
  • Updates response writing and file I/O to accept AsyncReader inputs.
  • Updates benchmarks/tests for the new body representation; several streaming-related tests are temporarily disabled during the migration.
File summaries
File Description
Tests/HummingbirdTests/PersistTests.swift Updates body collection/string decoding for UniqueArray<UInt8>.
Tests/HummingbirdTests/MiddlewareTests.swift Temporarily disables response-writer middleware streaming tests.
Tests/HummingbirdTests/FileIOTests.swift Switches FileIO write test to request.body.reader.
Tests/HummingbirdTests/ApplicationTests.swift Migrates body APIs; temporarily disables streaming/bidirectional streaming tests.
Tests/HummingbirdRouterTests/MiddlewareTests.swift Temporarily disables response-writer middleware streaming tests.
Tests/HummingbirdCoreTests/RequestBodyTests.swift Updates request-body tests to construct via BaseRequestAsyncReader; disables inbound-close-handler tests.
Tests/HummingbirdCoreTests/HTTP1ChannelTests.swift Updates expectations from readableBytes to count.
Tests/HummingbirdCoreTests/CoreTests.swift Updates request/response body writing to new reader/buffer model; adds a delayed reader helper.
Sources/PerformanceTest/main.swift Temporarily disables request-body echo path relying on async-sequence body.
Sources/HummingbirdTesting/RouterTestFramework.swift Updates test request construction to use BaseRequestAsyncReader.
Sources/HummingbirdHTTP2/HTTP2StreamChannel.swift Builds RequestBody via reader-state/reader; adjusts post-response inbound waiting logic.
Sources/HummingbirdCore/Utils/Disconnected.swift Adds _Disconnected helper for moving non-Sendable values across isolation.
Sources/HummingbirdCore/Utils/AnyAsyncSequence.swift Removes AnyAsyncSequence helper used by old request-body async-sequence model.
Sources/HummingbirdCore/Server/HTTP/HTTPChannelHandler.swift Switches request construction to reader-backed bodies and drains bodies post-response for keep-alive.
Sources/HummingbirdCore/Response/ResponseBodyWriter.swift Adds write(_ reader:) overload for AsyncReader of UniqueArray<UInt8>.
Sources/HummingbirdCore/Request/RequestBodyMergedWithUnderlyingRequestPartIterator.swift Temporarily disabled pending RequestAsyncReader migration.
Sources/HummingbirdCore/Request/RequestBody+inboundClose.swift Temporarily disabled pending RequestAsyncReader migration (consumeWithInboundCloseHandler).
Sources/HummingbirdCore/Request/RequestBody.swift Replaces async-sequence backing with move-only reader backing; adds collect, pipe, drain, forEachBuffer.
Sources/HummingbirdCore/Request/RequestAsyncReader.swift Introduces RequestAsyncReader, base channel-backed implementation, and collated reader.
Sources/HummingbirdCore/Request/Request.swift Makes body a stored RequestBody and updates collectBody semantics/signature.
Sources/Hummingbird/Server/Request.swift Removes unavailable legacy collate shim.
Sources/Hummingbird/Middleware/MetricsMiddleware.swift Avoids capturing non-sendable request by copying method before closure.
Sources/Hummingbird/Files/FileIO.swift Adds writeFile(reader:path:context:) overload for AsyncReader of UniqueArray<UInt8>.
Sources/Hummingbird/Exports.swift Updates export of RequestBody to class instead of struct.
Sources/Hummingbird/Error/RequestAsyncReaderError+HTTPError.swift Maps RequestAsyncReaderError to HTTP errors (e.g. payload too large).
Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedForm+Request.swift Updates request decoding to work from UniqueArray<UInt8> span.
Sources/Hummingbird/Codable/JSON/JSONCoding.swift Updates JSON decoding to work from UniqueArray<UInt8> span.
Benchmarks/HummingbirdBenchmarks/RouterBenchmarks.swift Updates benchmark request-body generation and body-size assertions.
Review details

Suppressed comments (1)

Tests/HummingbirdTests/MiddlewareTests.swift:149

  • Response-body-writer middleware tests are commented out, which removes coverage for ResponseBodyWriter composition during the RequestAsyncReader migration. Replacing these with reader-based request streaming assertions would help ensure the new ResponseBodyWriter.write(_ reader:) path works end-to-end.
    /* TODO: Fixup for RequestAsyncReader
    @Test func testMiddlewareResponseBodyWriter() async throws {
        struct TransformWriter: ResponseBodyWriter {
            var parentWriter: any ResponseBodyWriter

  • Files reviewed: 28/28 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Sources/HummingbirdHTTP2/HTTP2StreamChannel.swift Outdated
Comment thread Tests/HummingbirdCoreTests/RequestBodyTests.swift
Comment thread Tests/HummingbirdTests/ApplicationTests.swift
Comment thread Sources/Hummingbird/Files/FileIO.swift Outdated
Comment thread Sources/HummingbirdCore/Request/Request.swift Outdated
Comment thread Sources/HummingbirdCore/Response/ResponseBodyWriter.swift Outdated
Added additional comments, fix up out of date comments
@adam-fowler
adam-fowler force-pushed the request-async-reader-v2 branch from 70b32cc to f3c6173 Compare September 9, 2026 16:54
@adam-fowler
adam-fowler requested a review from tib September 9, 2026 18:20
@adam-fowler adam-fowler changed the title Use AsyncReader in RequestBody swift-http-server: Use AsyncReader in RequestBody Sep 10, 2026
@adam-fowler adam-fowler added the swift-http-server Work related to merging with swift-http-api-proposal and swift-http-server label Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

swift-http-server Work related to merging with swift-http-api-proposal and swift-http-server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants