Skip to content

Commit e18db27

Browse files
authored
Replace TransactionBody with NIOAsyncSequenceProducer (#677)
* save progress * Replace `TransactionBody` with `NIOAsyncSequenceProducer` * test * revert unnesscary changes * Add end-to-end test which currently fails because of apple/swift-nio#2398 * soundness * Use latest swift-nio release * throw CancellationError on task cancelation * Fix Swift 5.5 & 5.6
1 parent 6c5058e commit e18db27

11 files changed

+221
-483
lines changed

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let package = Package(
2121
.library(name: "AsyncHTTPClient", targets: ["AsyncHTTPClient"]),
2222
],
2323
dependencies: [
24-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.42.0"),
24+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.50.0"),
2525
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.22.0"),
2626
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.19.0"),
2727
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.13.0"),

[email protected]

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let package = Package(
2121
.library(name: "AsyncHTTPClient", targets: ["AsyncHTTPClient"]),
2222
],
2323
dependencies: [
24-
.package(url: "https://github.com/apple/swift-nio.git", from: "2.42.0"),
24+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.50.0"),
2525
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.22.0"),
2626
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.19.0"),
2727
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.13.0"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the AsyncHTTPClient open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the AsyncHTTPClient project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import NIOCore
16+
17+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
18+
@usableFromInline
19+
struct AnyAsyncSequenceProducerDelegate: NIOAsyncSequenceProducerDelegate {
20+
@usableFromInline
21+
var delegate: NIOAsyncSequenceProducerDelegate
22+
23+
@inlinable
24+
init<Delegate: NIOAsyncSequenceProducerDelegate>(_ delegate: Delegate) {
25+
self.delegate = delegate
26+
}
27+
28+
@inlinable
29+
func produceMore() {
30+
self.delegate.produceMore()
31+
}
32+
33+
@inlinable
34+
func didTerminate() {
35+
self.delegate.didTerminate()
36+
}
37+
}

Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift

+28-12
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,25 @@ public struct HTTPClientResponse: Sendable {
4545
}
4646

4747
init(
48-
bag: Transaction,
48+
requestMethod: HTTPMethod,
4949
version: HTTPVersion,
5050
status: HTTPResponseStatus,
5151
headers: HTTPHeaders,
52-
requestMethod: HTTPMethod
52+
body: TransactionBody
5353
) {
54-
let contentLength = HTTPClientResponse.expectedContentLength(requestMethod: requestMethod, headers: headers, status: status)
55-
self.init(version: version, status: status, headers: headers, body: .init(TransactionBody(bag, expectedContentLength: contentLength)))
54+
self.init(
55+
version: version,
56+
status: status,
57+
headers: headers,
58+
body: .init(.transaction(
59+
body,
60+
expectedContentLength: HTTPClientResponse.expectedContentLength(
61+
requestMethod: requestMethod,
62+
headers: headers,
63+
status: status
64+
)
65+
))
66+
)
5667
}
5768
}
5869

@@ -94,8 +105,8 @@ extension HTTPClientResponse {
94105
/// - Returns: the number of bytes collected over time
95106
@inlinable public func collect(upTo maxBytes: Int) async throws -> ByteBuffer {
96107
switch self.storage {
97-
case .transaction(let transactionBody):
98-
if let contentLength = transactionBody.expectedContentLength {
108+
case .transaction(_, let expectedContentLength):
109+
if let contentLength = expectedContentLength {
99110
if contentLength > maxBytes {
100111
throw NIOTooManyBytesError()
101112
}
@@ -127,10 +138,19 @@ extension HTTPClientResponse {
127138
}
128139
}
129140

141+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
142+
@usableFromInline
143+
typealias TransactionBody = NIOThrowingAsyncSequenceProducer<
144+
ByteBuffer,
145+
Error,
146+
NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark,
147+
AnyAsyncSequenceProducerDelegate
148+
>
149+
130150
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
131151
extension HTTPClientResponse.Body {
132152
@usableFromInline enum Storage: Sendable {
133-
case transaction(TransactionBody)
153+
case transaction(TransactionBody, expectedContentLength: Int?)
134154
case anyAsyncSequence(AnyAsyncSequence<ByteBuffer>)
135155
}
136156
}
@@ -141,7 +161,7 @@ extension HTTPClientResponse.Body.Storage: AsyncSequence {
141161

142162
@inlinable func makeAsyncIterator() -> AsyncIterator {
143163
switch self {
144-
case .transaction(let transaction):
164+
case .transaction(let transaction, _):
145165
return .transaction(transaction.makeAsyncIterator())
146166
case .anyAsyncSequence(let anyAsyncSequence):
147167
return .anyAsyncSequence(anyAsyncSequence.makeAsyncIterator())
@@ -172,10 +192,6 @@ extension HTTPClientResponse.Body.Storage.AsyncIterator: AsyncIteratorProtocol {
172192

173193
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
174194
extension HTTPClientResponse.Body {
175-
init(_ body: TransactionBody) {
176-
self.init(storage: .transaction(body))
177-
}
178-
179195
@inlinable init(_ storage: Storage) {
180196
self.storage = storage
181197
}

0 commit comments

Comments
 (0)