From ad4f7eaec53db3e2536e9b820b9d49fe871362a0 Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Mon, 8 Apr 2024 20:52:34 +0300 Subject: [PATCH 01/12] Some handy extensions to work with HTTPClientResponse body --- .../AsyncAwait/HTTPClientResponse.swift | 13 +++++++++++++ Sources/AsyncHTTPClient/FoundationExtensions.swift | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index ee7f11592..4476c90c4 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -138,6 +138,19 @@ extension HTTPClientResponse { } } +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension HTTPClientResponse { + /// Response body as `ByteBuffer`. + public var bytes: ByteBuffer { + get async throws { + let expectedBytes = headers + .first(name: "content-length") + .flatMap(Int.init) ?? 1024 * 1024 + return try await body.collect(upTo: expectedBytes) + } + } +} + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) @usableFromInline typealias TransactionBody = NIOThrowingAsyncSequenceProducer< diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index 545da756b..ca27f2459 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -64,3 +64,14 @@ extension HTTPClient.Body { return self.bytes(data) } } + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension HTTPClientResponse { + /// Response body as `Data`. + public var data: Data? { + get async throws { + var bytes = try await bytes + return bytes.readData(length: bytes.readableBytes) + } + } +} From 08795eaaf5924754ba60ee9bd8ada9eee187732c Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Mon, 8 Apr 2024 21:09:07 +0300 Subject: [PATCH 02/12] spaces --- .../AsyncAwait/HTTPClientResponse.swift | 18 +++++++++--------- .../AsyncHTTPClient/FoundationExtensions.swift | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index 4476c90c4..8ae819a88 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -140,15 +140,15 @@ extension HTTPClientResponse { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse { - /// Response body as `ByteBuffer`. - public var bytes: ByteBuffer { - get async throws { - let expectedBytes = headers - .first(name: "content-length") - .flatMap(Int.init) ?? 1024 * 1024 - return try await body.collect(upTo: expectedBytes) - } - } + /// Response body as `ByteBuffer`. + public var bytes: ByteBuffer { + get async throws { + let expectedBytes = headers + .first(name: "content-length") + .flatMap(Int.init) ?? 1024 * 1024 + return try await body.collect(upTo: expectedBytes) + } + } } @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index ca27f2459..f5c747e04 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -67,11 +67,11 @@ extension HTTPClient.Body { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse { - /// Response body as `Data`. - public var data: Data? { - get async throws { - var bytes = try await bytes - return bytes.readData(length: bytes.readableBytes) - } - } + /// Response body as `Data`. + public var data: Data? { + get async throws { + var bytes = try await bytes + return bytes.readData(length: bytes.readableBytes) + } + } } From 8f1e2eaf38183816b5d51ebf08012d1641a081cf Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 9 Apr 2024 12:07:32 +0300 Subject: [PATCH 03/12] use self.bytes --- Sources/AsyncHTTPClient/FoundationExtensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index f5c747e04..95b8cf905 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -70,7 +70,7 @@ extension HTTPClientResponse { /// Response body as `Data`. public var data: Data? { get async throws { - var bytes = try await bytes + var bytes = try await self.bytes return bytes.readData(length: bytes.readableBytes) } } From 7e0ebe21d01b1f5f9e15999e2d39bb0cbd1f211b Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 9 Apr 2024 12:11:23 +0300 Subject: [PATCH 04/12] changed bytes from a computed property to a func. Removed 1Mb expected bytes --- .../AsyncAwait/HTTPClientResponse.swift | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index 8ae819a88..a46e2b4d8 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -141,13 +141,18 @@ extension HTTPClientResponse { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse { /// Response body as `ByteBuffer`. - public var bytes: ByteBuffer { - get async throws { - let expectedBytes = headers - .first(name: "content-length") - .flatMap(Int.init) ?? 1024 * 1024 - return try await body.collect(upTo: expectedBytes) + /// - Returns: Bytes collected over time + public func bytes() async throws -> ByteBuffer { + if let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) { + return try await self.body.collect(upTo: expectedBytes) } + + var data = [UInt8]() + for try await var buffer in self.body { + data = data + (buffer.readBytes(length: buffer.readableBytes) ?? []) + } + + return ByteBuffer(bytes: data) } } From 47930100caee93769b81d613f9f681faafa5f3f7 Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 9 Apr 2024 12:11:38 +0300 Subject: [PATCH 05/12] use bytes() --- Sources/AsyncHTTPClient/FoundationExtensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index 95b8cf905..68de0723e 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -70,7 +70,7 @@ extension HTTPClientResponse { /// Response body as `Data`. public var data: Data? { get async throws { - var bytes = try await self.bytes + var bytes = try await self.bytes() return bytes.readData(length: bytes.readableBytes) } } From 7debf11242af72f02d9c4031d89cd026100f46ed Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 9 Apr 2024 12:36:07 +0300 Subject: [PATCH 06/12] added tests for new helpers --- .../AsyncAwaitEndToEndTests.swift | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift index a30a8cf91..bd62f7be5 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift @@ -835,6 +835,50 @@ final class AsyncAwaitEndToEndTests: XCTestCase { } } } + + func testResponseBytesHelper() { + XCTAsyncTest { + let bin = HTTPBin(.http2(compress: false)) { _ in HTTPEchoHandler() } + defer { XCTAssertNoThrow(try bin.shutdown()) } + let client = makeDefaultHTTPClient() + defer { XCTAssertNoThrow(try client.syncShutdown()) } + let logger = Logger(label: "HTTPClient", factory: StreamLogHandler.standardOutput(label:)) + var request = HTTPClientRequest(url: "https://localhost:\(bin.port)/") + request.method = .POST + request.body = .bytes(ByteBuffer(string: "1234")) + + guard let response = await XCTAssertNoThrowWithResult( + try await client.execute(request, deadline: .now() + .seconds(10), logger: logger) + ) else { return } + XCTAssertEqual(response.headers["content-length"], ["4"]) + guard let body = await XCTAssertNoThrowWithResult( + try await response.bytes() + ) else { return } + XCTAssertEqual(body, ByteBuffer(string: "1234")) + } + } + + func testResponseBodyDataHelper() { + XCTAsyncTest { + let bin = HTTPBin(.http2(compress: false)) { _ in HTTPEchoHandler() } + defer { XCTAssertNoThrow(try bin.shutdown()) } + let client = makeDefaultHTTPClient() + defer { XCTAssertNoThrow(try client.syncShutdown()) } + let logger = Logger(label: "HTTPClient", factory: StreamLogHandler.standardOutput(label:)) + var request = HTTPClientRequest(url: "https://localhost:\(bin.port)/") + request.method = .POST + request.body = .bytes(ByteBuffer(string: "1234")) + + guard let response = await XCTAssertNoThrowWithResult( + try await client.execute(request, deadline: .now() + .seconds(10), logger: logger) + ) else { return } + XCTAssertEqual(response.headers["content-length"], ["4"]) + guard let bodyData = await XCTAssertNoThrowWithResult( + try await response.data + ) else { return } + XCTAssertEqual(bodyData, "1234".data(using: .utf8)) + } + } } struct AnySendableSequence: @unchecked Sendable { From 06d365fa6ce79433504fb10068ce3ec0f60aff71 Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 9 Apr 2024 12:54:03 +0300 Subject: [PATCH 07/12] maxBytes param for bytes() func. tests updated --- .../AsyncAwait/HTTPClientResponse.swift | 6 ++++-- .../AsyncAwaitEndToEndTests.swift | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index a46e2b4d8..c598aefa9 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -141,9 +141,11 @@ extension HTTPClientResponse { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse { /// Response body as `ByteBuffer`. + /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. + /// Will accumulate all available bytes if nil passed. /// - Returns: Bytes collected over time - public func bytes() async throws -> ByteBuffer { - if let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) { + public func bytes(upTo maxBytes: Int? = nil) async throws -> ByteBuffer { + if let expectedBytes = maxBytes ?? self.headers.first(name: "content-length").flatMap(Int.init) { return try await self.body.collect(upTo: expectedBytes) } diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift index bd62f7be5..be1b3f43e 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift @@ -852,9 +852,18 @@ final class AsyncAwaitEndToEndTests: XCTestCase { ) else { return } XCTAssertEqual(response.headers["content-length"], ["4"]) guard let body = await XCTAssertNoThrowWithResult( - try await response.bytes() + try await response.bytes(upTo: 4) ) else { return } XCTAssertEqual(body, ByteBuffer(string: "1234")) + + guard var responseNoContentLength = await XCTAssertNoThrowWithResult( + try await client.execute(request, deadline: .now() + .seconds(10), logger: logger) + ) else { return } + responseNoContentLength.headers.remove(name: "content-length") + guard let body2 = await XCTAssertNoThrowWithResult( + try await responseNoContentLength.bytes() + ) else { return } + XCTAssertEqual(body2, ByteBuffer(string: "1234")) } } From d76e399cea051ba3d633f9468a33d69af4821969 Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Tue, 16 Apr 2024 00:44:01 +0300 Subject: [PATCH 08/12] Made upTo a required parameter for bytes and data extensions --- .../AsyncAwait/HTTPClientResponse.swift | 15 +++------------ .../AsyncHTTPClient/FoundationExtensions.swift | 10 +++++----- .../AsyncAwaitEndToEndTests.swift | 6 +++--- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index c598aefa9..24b194b10 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -142,19 +142,10 @@ extension HTTPClientResponse { extension HTTPClientResponse { /// Response body as `ByteBuffer`. /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. - /// Will accumulate all available bytes if nil passed. /// - Returns: Bytes collected over time - public func bytes(upTo maxBytes: Int? = nil) async throws -> ByteBuffer { - if let expectedBytes = maxBytes ?? self.headers.first(name: "content-length").flatMap(Int.init) { - return try await self.body.collect(upTo: expectedBytes) - } - - var data = [UInt8]() - for try await var buffer in self.body { - data = data + (buffer.readBytes(length: buffer.readableBytes) ?? []) - } - - return ByteBuffer(bytes: data) + public func bytes(upTo maxBytes: Int) async throws -> ByteBuffer { + let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) ?? maxBytes + return try await self.body.collect(upTo: expectedBytes) } } diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index 68de0723e..42b95b6d8 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -68,10 +68,10 @@ extension HTTPClient.Body { @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension HTTPClientResponse { /// Response body as `Data`. - public var data: Data? { - get async throws { - var bytes = try await self.bytes() - return bytes.readData(length: bytes.readableBytes) - } + /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. + /// - Returns: Bytes collected over time + public func data(upTo maxBytes: Int) async throws -> Data? { + var bytes = try await self.bytes(upTo: maxBytes) + return bytes.readData(length: bytes.readableBytes) } } diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift index be1b3f43e..bfce896b6 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift @@ -852,7 +852,7 @@ final class AsyncAwaitEndToEndTests: XCTestCase { ) else { return } XCTAssertEqual(response.headers["content-length"], ["4"]) guard let body = await XCTAssertNoThrowWithResult( - try await response.bytes(upTo: 4) + try await response.bytes(upTo: 3) ) else { return } XCTAssertEqual(body, ByteBuffer(string: "1234")) @@ -861,7 +861,7 @@ final class AsyncAwaitEndToEndTests: XCTestCase { ) else { return } responseNoContentLength.headers.remove(name: "content-length") guard let body2 = await XCTAssertNoThrowWithResult( - try await responseNoContentLength.bytes() + try await responseNoContentLength.bytes(upTo: 4) ) else { return } XCTAssertEqual(body2, ByteBuffer(string: "1234")) } @@ -883,7 +883,7 @@ final class AsyncAwaitEndToEndTests: XCTestCase { ) else { return } XCTAssertEqual(response.headers["content-length"], ["4"]) guard let bodyData = await XCTAssertNoThrowWithResult( - try await response.data + try await response.data(upTo: 4) ) else { return } XCTAssertEqual(bodyData, "1234".data(using: .utf8)) } From 9bdd6efdd55b19a5374c242346db9c503260acbe Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Fri, 8 Aug 2025 22:44:08 +0700 Subject: [PATCH 09/12] updated extensions --- .../AsyncAwait/HTTPClientResponse+data.swift | 41 +++++++++++++++++++ .../AsyncAwait/HTTPClientResponse.swift | 11 ----- .../FoundationExtensions.swift | 11 ----- .../AsyncAwaitEndToEndTests.swift | 2 +- 4 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift new file mode 100644 index 000000000..44099a420 --- /dev/null +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the AsyncHTTPClient open source project +// +// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import NIOCore +import NIOHTTP1 +import Foundation +internal import NIOFoundationCompat + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension HTTPClientResponse { + /// Response body as `ByteBuffer`. + /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. + /// - Returns: Bytes collected over time + public func bytes(upTo maxBytes: Int) async throws -> ByteBuffer { + let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) ?? maxBytes + return try await self.body.collect(upTo: min(expectedBytes, maxBytes)) + } +} + + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension HTTPClientResponse { + /// Response body as `Data`. + /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. + /// - Returns: Bytes collected over time + public func data(upTo maxBytes: Int) async throws -> Data? { + var bytes = try await self.bytes(upTo: maxBytes) + return bytes.readData(length: bytes.readableBytes) + } +} diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift index a8b1180b2..36c1cb36f 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse.swift @@ -187,17 +187,6 @@ extension HTTPClientResponse { } } -@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -extension HTTPClientResponse { - /// Response body as `ByteBuffer`. - /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. - /// - Returns: Bytes collected over time - public func bytes(upTo maxBytes: Int) async throws -> ByteBuffer { - let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) ?? maxBytes - return try await self.body.collect(upTo: expectedBytes) - } -} - @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) @usableFromInline typealias TransactionBody = NIOThrowingAsyncSequenceProducer< diff --git a/Sources/AsyncHTTPClient/FoundationExtensions.swift b/Sources/AsyncHTTPClient/FoundationExtensions.swift index 1a7e9bb5c..452cb7b13 100644 --- a/Sources/AsyncHTTPClient/FoundationExtensions.swift +++ b/Sources/AsyncHTTPClient/FoundationExtensions.swift @@ -73,14 +73,3 @@ extension HTTPClient.Body { self.bytes(data) } } - -@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -extension HTTPClientResponse { - /// Response body as `Data`. - /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. - /// - Returns: Bytes collected over time - public func data(upTo maxBytes: Int) async throws -> Data? { - var bytes = try await self.bytes(upTo: maxBytes) - return bytes.readData(length: bytes.readableBytes) - } -} diff --git a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift index 882be09cc..9f3da4085 100644 --- a/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift +++ b/Tests/AsyncHTTPClientTests/AsyncAwaitEndToEndTests.swift @@ -1036,7 +1036,7 @@ final class AsyncAwaitEndToEndTests: XCTestCase { ) else { return } XCTAssertEqual(response.headers["content-length"], ["4"]) guard let body = await XCTAssertNoThrowWithResult( - try await response.bytes(upTo: 3) + try await response.bytes(upTo: 5) ) else { return } XCTAssertEqual(body, ByteBuffer(string: "1234")) From 6918617d382cda0e3e1b33790dd6a13f282ac9bc Mon Sep 17 00:00:00 2001 From: Sergey Date: Fri, 15 Aug 2025 22:20:38 +0700 Subject: [PATCH 10/12] Update Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift Co-authored-by: Cory Benfield --- .../AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift index 44099a420..fb1a9ab4a 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift @@ -2,7 +2,7 @@ // // This source file is part of the AsyncHTTPClient open source project // -// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors +// Copyright (c) 2025 Apple Inc. and the AsyncHTTPClient project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information From db0373b18742d0efce426ac07d659019137ff912 Mon Sep 17 00:00:00 2001 From: Sergey Date: Fri, 15 Aug 2025 22:20:54 +0700 Subject: [PATCH 11/12] Update Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift Co-authored-by: Cory Benfield --- .../AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift index fb1a9ab4a..d9ae4ad1d 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift @@ -14,7 +14,11 @@ import NIOCore import NIOHTTP1 +#if canImport(FoundationEssentials) +import FoundationEssentials +#else import Foundation +#endif internal import NIOFoundationCompat @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) From d12311fc2c1c566d272c778894e309f8231976a3 Mon Sep 17 00:00:00 2001 From: Sergey Armodin Date: Fri, 15 Aug 2025 22:25:45 +0700 Subject: [PATCH 12/12] always use maxBytes --- .../AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift index d9ae4ad1d..389442820 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientResponse+data.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import NIOCore -import NIOHTTP1 #if canImport(FoundationEssentials) import FoundationEssentials #else @@ -27,8 +26,7 @@ extension HTTPClientResponse { /// - Parameter maxBytes: The maximum number of bytes this method is allowed to accumulate. /// - Returns: Bytes collected over time public func bytes(upTo maxBytes: Int) async throws -> ByteBuffer { - let expectedBytes = self.headers.first(name: "content-length").flatMap(Int.init) ?? maxBytes - return try await self.body.collect(upTo: min(expectedBytes, maxBytes)) + return try await self.body.collect(upTo: maxBytes) } }