From ea8eccfb2cef417914ad50feec4814a14e7bbab5 Mon Sep 17 00:00:00 2001 From: Guoye Zhang Date: Mon, 29 Jun 2026 10:22:30 -0700 Subject: [PATCH 1/2] Add trailers and request body streaming experimental SPIs --- Package.swift | 10 ++++ .../HTTPClientRequest+Prepared.swift | 11 ++++ .../AsyncAwait/HTTPClientRequest.swift | 52 ++++++++++++++++ .../AsyncAwait/HTTPClientResponse.swift | 20 ++++++- .../AsyncAwait/Transaction+StateMachine.swift | 59 ++++++++++++------- .../AsyncAwait/Transaction.swift | 34 ++++++++--- .../HTTPClientRequestTests.swift | 4 ++ .../HTTPClientTestUtils.swift | 15 +++-- 8 files changed, 167 insertions(+), 38 deletions(-) diff --git a/Package.swift b/Package.swift index 7ab335bc6..33390651a 100644 --- a/Package.swift +++ b/Package.swift @@ -34,6 +34,16 @@ let package = Package( products: [ .library(name: "AsyncHTTPClient", targets: ["AsyncHTTPClient"]) ], + traits: [ + .default(enabledTraits: []), + .trait( + name: "ExperimentalHTTPAPIsSupport", + description: """ + Enables source unstable SPIs to support the swift-http-api-proposal + AHC backend. Do not rely on this module in API stable packages. + """ + ), + ], dependencies: [ .package(url: "https://github.com/apple/swift-nio.git", from: "2.100.0"), .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.30.0"), diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift index 6729876f3..f6e947c68 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift @@ -38,6 +38,9 @@ extension HTTPClientRequest { makeCompleteBody: @Sendable (ByteBufferAllocator) -> ByteBuffer ) case byteBuffer(ByteBuffer) + #if ExperimentalHTTPAPIsSupport + case httpClientRequestBody(RequestBodyLength, HTTPClientRequest.Body.RequestWriterContinuation) + #endif } var url: URL @@ -111,6 +114,10 @@ extension HTTPClientRequest.Prepared.Body { ) case .byteBuffer(let byteBuffer): self = .byteBuffer(byteBuffer) + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody(let length, let requestBody): + self = .httpClientRequestBody(length, requestBody) + #endif } } } @@ -125,6 +132,10 @@ extension RequestBodyLength { self = .known(Int64(buffer.readableBytes)) case .sequence(let length, _, _), .asyncSequence(let length, _): self = length + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody(let length, _): + self = length + #endif } } } diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift index 5fb5f5cb5..2c2cdd9b6 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift @@ -100,6 +100,13 @@ extension HTTPClientRequest { makeCompleteBody: @Sendable (ByteBufferAllocator) -> ByteBuffer ) case byteBuffer(ByteBuffer) + + #if ExperimentalHTTPAPIsSupport + case httpClientRequestBody( + length: RequestBodyLength, + startUpload: RequestWriterContinuation + ) + #endif } @usableFromInline @@ -109,6 +116,44 @@ extension HTTPClientRequest { internal init(_ mode: Mode) { self.mode = mode } + + #if ExperimentalHTTPAPIsSupport + public init(length: Int64?, startUpload: AsyncStream.Continuation) { + let length = length.map { RequestBodyLength.known($0) } ?? .unknown + self.init( + .httpClientRequestBody( + length: length, + startUpload: RequestWriterContinuation(continuation: startUpload) + ) + ) + } + + @usableFromInline + struct RequestWriterContinuation: Sendable { + var continuation: AsyncStream.Continuation + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public struct RequestWriter: Sendable { + @usableFromInline + let transaction: Transaction + + @inlinable + public func writeRequestBodyPart(_ buffer: ByteBuffer) async throws { + try await self.transaction.writeRequestBodyPart(buffer) + } + + @inlinable + public func requestBodyStreamFinished(trailers: HTTPHeaders?) { + self.transaction.requestBodyStreamFinished(trailers: trailers) + } + + @inlinable + public func fail(_ error: any Error) { + self.transaction.fail(error) + } + } + #endif } } @@ -353,6 +398,9 @@ extension Optional where Wrapped == HTTPClientRequest.Body { case .byteBuffer: return true case .sequence(_, let canBeConsumedMultipleTimes, _): return canBeConsumedMultipleTimes case .asyncSequence: return false + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody: return false // TODO: I think this should be TRUE + #endif } } } @@ -393,6 +441,10 @@ extension HTTPClientRequest.Body: AsyncSequence { return .init(storage: .byteBuffer(makeCompleteBody(AsyncIterator.allocator))) case .byteBuffer(let byteBuffer): return .init(storage: .byteBuffer(byteBuffer)) + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody: + fatalError("Unimplemented") + #endif } } } diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index 13c08f19f..e29e33c95 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -82,6 +82,7 @@ public struct HTTPClientResponse: Sendable { version: HTTPVersion, status: HTTPResponseStatus, headers: HTTPHeaders, + transaction: Transaction, body: TransactionBody, history: [HTTPClientRequestResponse] ) { @@ -92,6 +93,7 @@ public struct HTTPClientResponse: Sendable { body: .init( .transaction( body, + transaction, expectedContentLength: HTTPClientResponse.expectedContentLength( requestMethod: requestMethod, headers: headers, @@ -153,7 +155,7 @@ extension HTTPClientResponse { /// - Returns: the number of bytes collected over time @inlinable public func collect(upTo maxBytes: Int) async throws -> ByteBuffer { switch self.storage { - case .transaction(_, let expectedContentLength): + case .transaction(_, _, let expectedContentLength): if let contentLength = expectedContentLength { if contentLength > maxBytes { throw NIOTooManyBytesError(maxBytes: maxBytes) @@ -170,6 +172,18 @@ extension HTTPClientResponse { } return try await collect(self, maxBytes: maxBytes) } + + #if ExperimentalHTTPAPIsSupport + public var trailers: HTTPHeaders? { + switch self.storage { + case .transaction(_, let transaction, _): + return transaction.trailers + + case .anyAsyncSequence: + return nil + } + } + #endif } } @@ -203,7 +217,7 @@ typealias TransactionBody = NIOThrowingAsyncSequenceProducer< @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse.Body { @usableFromInline enum Storage: Sendable { - case transaction(TransactionBody, expectedContentLength: Int?) + case transaction(TransactionBody, Transaction, expectedContentLength: Int?) case anyAsyncSequence(AnyAsyncSequence) } } @@ -214,7 +228,7 @@ extension HTTPClientResponse.Body.Storage: AsyncSequence { @inlinable func makeAsyncIterator() -> AsyncIterator { switch self { - case .transaction(let transaction, _): + case .transaction(let transaction, _, _): return .transaction(transaction.makeAsyncIterator()) case .anyAsyncSequence(let anyAsyncSequence): return .anyAsyncSequence(anyAsyncSequence.makeAsyncIterator()) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift b/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift index 4128998b9..01f01d43c 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift @@ -31,7 +31,7 @@ extension Transaction { case queued(CheckedContinuation, HTTPRequestScheduler) case deadlineExceededWhileQueued(CheckedContinuation) case executing(ExecutionContext, RequestStreamState, ResponseStreamState) - case finished(error: Error?) + case finished(Result) } fileprivate enum RequestStreamState: Sendable { @@ -47,7 +47,7 @@ extension Transaction { case waitingForResponseHead // streaming response body. Valid transitions to: finished. case streamingBody(TransactionBody.Source) - case finished + case finished(HTTPHeaders?) } private var state: State @@ -105,11 +105,11 @@ extension Transaction { mutating func fail(_ error: Error) -> FailAction { switch self.state { case .initialized(let continuation): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .failResponseHead(continuation, error, nil, nil, bodyStreamContinuation: nil) case .queued(let continuation, let scheduler): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .failResponseHead(continuation, error, scheduler, nil, bodyStreamContinuation: nil) case .deadlineExceededWhileQueued(let continuation): let realError: Error = { @@ -123,12 +123,12 @@ extension Transaction { } }() - self.state = .finished(error: realError) + self.state = .finished(.failure(realError)) return .failResponseHead(continuation, realError, nil, nil, bodyStreamContinuation: nil) case .executing(let context, let requestStreamState, .waitingForResponseHead): switch requestStreamState { case .paused(continuation: .some(let continuation)): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .failResponseHead( context.continuation, error, @@ -138,7 +138,7 @@ extension Transaction { ) case .requestHeadSent, .endForwarded, .finished, .producing, .paused(continuation: .none): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .failResponseHead( context.continuation, error, @@ -149,7 +149,7 @@ extension Transaction { } case .executing(let context, let requestStreamState, .streamingBody(let source)): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) switch requestStreamState { case .paused(let bodyStreamContinuation): return .failResponseStream( @@ -164,7 +164,7 @@ extension Transaction { case .executing(let context, let requestStreamState, .finished): // an error occured after full response received, but before the full request was sent - self.state = .finished(error: error) + self.state = .finished(.failure(error)) switch requestStreamState { case .paused(let bodyStreamContinuation): if let bodyStreamContinuation { @@ -205,14 +205,14 @@ extension Transaction { return .none case .deadlineExceededWhileQueued(let continuation): let error = HTTPClientError.deadlineExceeded - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .cancelAndFail(executor, continuation, with: error) - case .finished(error: .some): + case .finished(.failure): return .cancel(executor) case .executing, - .finished(error: .none): + .finished(.success): preconditionFailure("Invalid state: \(self.state)") } } @@ -402,8 +402,8 @@ extension Transaction { assertionFailure("Invalid state: \(self.state)") return .failure(HTTPClientError.internalStateFailure()) - case .executing(_, .endForwarded, .finished): - self.state = .finished(error: nil) + case .executing(_, .endForwarded, .finished(let trailers)): + self.state = .finished(.success(trailers)) return .none case .executing(let context, .endForwarded, let responseState): @@ -446,12 +446,12 @@ extension Transaction { self.state = .executing(context, requestState, .streamingBody(body.source)) return .succeedResponseHead(body.sequence, context.continuation) - case .finished(error: .some): + case .finished(.failure): // If the request failed before, we don't need to do anything in response to // receiving the response head. return .none - case .finished(error: .none): + case .finished(.success): preconditionFailure("How can the request be finished without error, before receiving response head?") } } @@ -511,7 +511,10 @@ extension Transaction { case none } - mutating func receiveResponseEnd(_ newChunks: CircularBuffer?) -> ReceiveResponseEndAction { + mutating func receiveResponseEnd( + _ newChunks: CircularBuffer?, + trailers: HTTPHeaders? + ) -> ReceiveResponseEndAction { switch self.state { case .initialized, .queued, @@ -524,9 +527,9 @@ extension Transaction { case .executing(let context, let requestState, .streamingBody(let source)): switch requestState { case .finished: - self.state = .finished(error: nil) + self.state = .finished(.success(trailers)) case .paused, .producing, .requestHeadSent, .endForwarded: - self.state = .executing(context, requestState, .finished) + self.state = .executing(context, requestState, .finished(trailers)) } return .finishResponseStream(source, finalBody: newChunks) @@ -540,6 +543,18 @@ extension Transaction { } } + var trailers: HTTPHeaders? { + switch self.state { + case .deadlineExceededWhileQueued, .initialized, .queued, + .executing(_, _, .waitingForResponseHead), + .executing(_, _, .streamingBody), + .finished(.failure): + return nil + case .executing(_, _, .finished(let trailers)), .finished(.success(let trailers)): + return trailers + } + } + mutating func httpResponseStreamTerminated() -> FailAction { switch self.state { case .executing(_, _, .finished), .finished: @@ -565,7 +580,7 @@ extension Transaction { let error = HTTPClientError.deadlineExceeded switch self.state { case .initialized(let continuation): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .cancel( requestContinuation: continuation, scheduler: nil, @@ -583,7 +598,7 @@ extension Transaction { case .executing(let context, let requestStreamState, .waitingForResponseHead): switch requestStreamState { case .paused(continuation: .some(let continuation)): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .cancel( requestContinuation: context.continuation, scheduler: nil, @@ -591,7 +606,7 @@ extension Transaction { bodyStreamContinuation: continuation ) case .requestHeadSent, .endForwarded, .finished, .producing, .paused(continuation: .none): - self.state = .finished(error: error) + self.state = .finished(.failure(error)) return .cancel( requestContinuation: context.continuation, scheduler: nil, diff --git a/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift b/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift index 30c7c877f..2e32a4cfd 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift @@ -17,6 +17,7 @@ import NIOConcurrencyHelpers import NIOCore import NIOHTTP1 import NIOSSL +import Synchronization import Tracing @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) @@ -73,7 +74,7 @@ final class Transaction: return } - self.requestBodyStreamFinished() + self.requestBodyStreamFinished(trailers: nil) } private func continueRequestBodyStream( @@ -94,7 +95,7 @@ final class Transaction: } } - self.requestBodyStreamFinished() + self.requestBodyStreamFinished(trailers: nil) } catch { // The only chance of reaching this catch block, is an error thrown in the `next` // call above. @@ -105,7 +106,8 @@ final class Transaction: struct BreakTheWriteLoopError: Swift.Error {} - private func writeRequestBodyPart(_ part: ByteBuffer) async throws { + @usableFromInline + func writeRequestBodyPart(_ part: ByteBuffer) async throws { let action = self.state.withLockedValue { state in state.writeNextRequestPart() } @@ -146,7 +148,8 @@ final class Transaction: } } - private func requestBodyStreamFinished() { + @usableFromInline + func requestBodyStreamFinished(trailers: HTTPHeaders?) { let finishAction = self.state.withLockedValue { state in state.finishRequestBodyStream() } @@ -157,7 +160,7 @@ final class Transaction: break case .forwardStreamFinished(let executor): - executor.finishRequestBodyStream(trailers: nil, request: self, promise: nil) + executor.finishRequestBodyStream(trailers: trailers, request: self, promise: nil) } return } @@ -228,12 +231,17 @@ extension Transaction: HTTPExecutableRequest { case .byteBuffer(let byteBuffer): self.writeOnceAndOneTimeOnly(byteBuffer: byteBuffer) - case .none: - break - case .sequence(_, _, let create): let byteBuffer = create(allocator) self.writeOnceAndOneTimeOnly(byteBuffer: byteBuffer) + + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody(_, let continuation): + continuation.continuation.yield(HTTPClientRequest.Body.RequestWriter(transaction: self)) + #endif + + case .none: + break } case .resumeStream(let continuation): @@ -277,6 +285,7 @@ extension Transaction: HTTPExecutableRequest { version: head.version, status: head.status, headers: head.headers, + transaction: self, body: body, history: [] ) @@ -303,7 +312,7 @@ extension Transaction: HTTPExecutableRequest { func receiveResponseEnd(_ buffer: CircularBuffer?, trailers: HTTPHeaders?) { let receiveResponseEndAction = self.state.withLockedValue { state in - state.receiveResponseEnd(buffer) + state.receiveResponseEnd(buffer, trailers: trailers) } switch receiveResponseEndAction { case .finishResponseStream(let source, let finalResponse): @@ -317,6 +326,12 @@ extension Transaction: HTTPExecutableRequest { } } + var trailers: HTTPHeaders? { + self.state.withLockedValue { + $0.trailers + } + } + func httpResponseStreamTerminated() { let action = self.state.withLockedValue { state in state.httpResponseStreamTerminated() @@ -324,6 +339,7 @@ extension Transaction: HTTPExecutableRequest { self.performFailAction(action) } + @usableFromInline func fail(_ error: Error) { let action = self.state.withLockedValue { state in state.fail(error) diff --git a/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift b/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift index 54467aab7..0b70ec559 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift @@ -782,6 +782,10 @@ extension Optional where Wrapped == HTTPClientRequest.Prepared.Body { ) } return accumulatedBuffer + #if ExperimentalHTTPAPIsSupport + case .httpClientRequestBody: + fatalError("TODO: Unimplemented") + #endif } } } diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTestUtils.swift b/Tests/AsyncHTTPClientTests/HTTPClientTestUtils.swift index abf6d82db..ea80cee6e 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientTestUtils.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientTestUtils.swift @@ -790,16 +790,19 @@ internal struct HTTPResponseBuilder { var body: ByteBuffer? var requestBodyByteCount: Int let responseBodyIsRequestBodyByteCount: Bool + let trailers: HTTPHeaders? init( _ version: HTTPVersion = HTTPVersion(major: 1, minor: 1), status: HTTPResponseStatus, headers: HTTPHeaders = HTTPHeaders(), - responseBodyIsRequestBodyByteCount: Bool = false + responseBodyIsRequestBodyByteCount: Bool = false, + trailers: HTTPHeaders? = nil ) { self.head = HTTPResponseHead(version: version, status: status, headers: headers) self.requestBodyByteCount = 0 self.responseBodyIsRequestBodyByteCount = responseBodyIsRequestBodyByteCount + self.trailers = trailers } mutating func add(_ part: ByteBuffer) { @@ -967,6 +970,9 @@ internal final class HTTPBinHandler: ChannelInboundHandler { } self.resps.append(HTTPResponseBuilder(status: .ok)) return + case "/trailers": + self.resps.append(HTTPResponseBuilder(status: .ok, trailers: ["hello": "world"])) + return case "/stats": var body = context.channel.allocator.buffer(capacity: 1) body.writeString("Just some stats mate.") @@ -1154,7 +1160,8 @@ internal final class HTTPBinHandler: ChannelInboundHandler { return } - context.writeAndFlush(self.wrapOutboundOut(.end(nil))).assumeIsolated().whenComplete { result in + context.writeAndFlush(self.wrapOutboundOut(.end(response.trailers))).assumeIsolated().whenComplete { + result in self.isServingRequest = false switch result { case .success: @@ -1485,8 +1492,8 @@ class HTTPEchoHandler: ChannelInboundHandler { ) case .body(let bytes): context.writeAndFlush(self.wrapOutboundOut(.body(.byteBuffer(bytes))), promise: nil) - case .end: - context.writeAndFlush(self.wrapOutboundOut(.end(nil))).assumeIsolated().whenSuccess { + case .end(let trailers): + context.writeAndFlush(self.wrapOutboundOut(.end(trailers))).assumeIsolated().whenSuccess { context.close(promise: nil) } } From 6969932035aebcc9d65ef82de8d1cf9a8c5bbaff Mon Sep 17 00:00:00 2001 From: Guoye Zhang Date: Mon, 29 Jun 2026 12:55:30 -0700 Subject: [PATCH 2/2] Rename trait --- Package.swift | 2 +- .../AsyncAwait/HTTPClientRequest+Prepared.swift | 6 +++--- .../AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift | 8 ++++---- .../AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift | 2 +- Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift | 2 +- Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Package.swift b/Package.swift index 33390651a..d08f7678f 100644 --- a/Package.swift +++ b/Package.swift @@ -37,7 +37,7 @@ let package = Package( traits: [ .default(enabledTraits: []), .trait( - name: "ExperimentalHTTPAPIsSupport", + name: "UnstableHTTPAPIsSupport", description: """ Enables source unstable SPIs to support the swift-http-api-proposal AHC backend. Do not rely on this module in API stable packages. diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift index f6e947c68..3e4482292 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest+Prepared.swift @@ -38,7 +38,7 @@ extension HTTPClientRequest { makeCompleteBody: @Sendable (ByteBufferAllocator) -> ByteBuffer ) case byteBuffer(ByteBuffer) - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case httpClientRequestBody(RequestBodyLength, HTTPClientRequest.Body.RequestWriterContinuation) #endif } @@ -114,7 +114,7 @@ extension HTTPClientRequest.Prepared.Body { ) case .byteBuffer(let byteBuffer): self = .byteBuffer(byteBuffer) - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody(let length, let requestBody): self = .httpClientRequestBody(length, requestBody) #endif @@ -132,7 +132,7 @@ extension RequestBodyLength { self = .known(Int64(buffer.readableBytes)) case .sequence(let length, _, _), .asyncSequence(let length, _): self = length - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody(let length, _): self = length #endif diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift index 2c2cdd9b6..17563a122 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift @@ -101,7 +101,7 @@ extension HTTPClientRequest { ) case byteBuffer(ByteBuffer) - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case httpClientRequestBody( length: RequestBodyLength, startUpload: RequestWriterContinuation @@ -117,7 +117,7 @@ extension HTTPClientRequest { self.mode = mode } - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport public init(length: Int64?, startUpload: AsyncStream.Continuation) { let length = length.map { RequestBodyLength.known($0) } ?? .unknown self.init( @@ -398,7 +398,7 @@ extension Optional where Wrapped == HTTPClientRequest.Body { case .byteBuffer: return true case .sequence(_, let canBeConsumedMultipleTimes, _): return canBeConsumedMultipleTimes case .asyncSequence: return false - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody: return false // TODO: I think this should be TRUE #endif } @@ -441,7 +441,7 @@ extension HTTPClientRequest.Body: AsyncSequence { return .init(storage: .byteBuffer(makeCompleteBody(AsyncIterator.allocator))) case .byteBuffer(let byteBuffer): return .init(storage: .byteBuffer(byteBuffer)) - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody: fatalError("Unimplemented") #endif diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index e29e33c95..e8d04f091 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -173,7 +173,7 @@ extension HTTPClientResponse { return try await collect(self, maxBytes: maxBytes) } - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport public var trailers: HTTPHeaders? { switch self.storage { case .transaction(_, let transaction, _): diff --git a/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift b/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift index 2e32a4cfd..0b62116cb 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift @@ -235,7 +235,7 @@ extension Transaction: HTTPExecutableRequest { let byteBuffer = create(allocator) self.writeOnceAndOneTimeOnly(byteBuffer: byteBuffer) - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody(_, let continuation): continuation.continuation.yield(HTTPClientRequest.Body.RequestWriter(transaction: self)) #endif diff --git a/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift b/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift index 0b70ec559..f28d3ed02 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientRequestTests.swift @@ -782,7 +782,7 @@ extension Optional where Wrapped == HTTPClientRequest.Prepared.Body { ) } return accumulatedBuffer - #if ExperimentalHTTPAPIsSupport + #if UnstableHTTPAPIsSupport case .httpClientRequestBody: fatalError("TODO: Unimplemented") #endif