@@ -20,7 +20,7 @@ import NIOHTTP1
2020///
2121/// This object is similar to ``HTTPClient/Request``, but used for the Swift Concurrency API.
2222@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
23- public struct HTTPClientRequest {
23+ public struct HTTPClientRequest : Sendable {
2424 /// The request URL, including scheme, hostname, and optionally port.
2525 public var url : String
2626
@@ -47,18 +47,18 @@ extension HTTPClientRequest {
4747 ///
4848 /// This object encapsulates the difference between streamed HTTP request bodies and those bodies that
4949 /// are already entirely in memory.
50- public struct Body {
50+ public struct Body : Sendable {
5151 @usableFromInline
52- internal enum Mode {
52+ internal enum Mode : Sendable {
5353 /// - parameters:
5454 /// - length: complete body length.
5555 /// If `length` is `.known`, `nextBodyPart` is not allowed to produce more bytes than `length` defines.
5656 /// - makeAsyncIterator: Creates a new async iterator under the hood and returns a function which will call `next()` on it.
5757 /// The returned function then produce the next body buffer asynchronously.
58- /// We use a closure as abstraction instead of an existential to enable specialization.
58+ /// We use a closure as an abstraction instead of an existential to enable specialization.
5959 case asyncSequence(
6060 length: RequestBodyLength ,
61- makeAsyncIterator: ( ) -> ( ( ByteBufferAllocator ) async throws -> ByteBuffer ? )
61+ makeAsyncIterator: @ Sendable ( ) -> ( ( ByteBufferAllocator ) async throws -> ByteBuffer ? )
6262 )
6363 /// - parameters:
6464 /// - length: complete body length.
@@ -68,7 +68,7 @@ extension HTTPClientRequest {
6868 case sequence(
6969 length: RequestBodyLength ,
7070 canBeConsumedMultipleTimes: Bool ,
71- makeCompleteBody: ( ByteBufferAllocator ) -> ByteBuffer
71+ makeCompleteBody: @ Sendable ( ByteBufferAllocator ) -> ByteBuffer
7272 )
7373 case byteBuffer( ByteBuffer )
7474 }
@@ -92,6 +92,22 @@ extension HTTPClientRequest.Body {
9292 self . init ( . byteBuffer( byteBuffer) )
9393 }
9494
95+ #if swift(>=5.6)
96+ /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `RandomAccessCollection` of bytes.
97+ ///
98+ /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
99+ /// usage of this construction will be double the size of the original collection. The construction
100+ /// of the `ByteBuffer` will be delayed until it's needed.
101+ ///
102+ /// - parameter bytes: The bytes of the request body.
103+ @inlinable
104+ @preconcurrency
105+ public static func bytes< Bytes: RandomAccessCollection & Sendable > (
106+ _ bytes: Bytes
107+ ) -> Self where Bytes. Element == UInt8 {
108+ Self . _bytes ( bytes)
109+ }
110+ #else
95111 /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `RandomAccessCollection` of bytes.
96112 ///
97113 /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
@@ -102,6 +118,14 @@ extension HTTPClientRequest.Body {
102118 @inlinable
103119 public static func bytes< Bytes: RandomAccessCollection > (
104120 _ bytes: Bytes
121+ ) -> Self where Bytes. Element == UInt8 {
122+ Self . _bytes ( bytes)
123+ }
124+ #endif
125+
126+ @inlinable
127+ static func _bytes< Bytes: RandomAccessCollection > (
128+ _ bytes: Bytes
105129 ) -> Self where Bytes. Element == UInt8 {
106130 self . init ( . sequence(
107131 length: . known( bytes. count) ,
@@ -116,6 +140,33 @@ extension HTTPClientRequest.Body {
116140 } )
117141 }
118142
143+ #if swift(>=5.6)
144+ /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `Sequence` of bytes.
145+ ///
146+ /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
147+ /// usage of this construction will be double the size of the original collection. The construction
148+ /// of the `ByteBuffer` will be delayed until it's needed.
149+ ///
150+ /// Unlike ``bytes(_:)-1uns7``, this construction does not assume that the body can be replayed. As a result,
151+ /// if a redirect is encountered that would need us to replay the request body, the redirect will instead
152+ /// not be followed. Prefer ``bytes(_:)-1uns7`` wherever possible.
153+ ///
154+ /// Caution should be taken with this method to ensure that the `length` is correct. Incorrect lengths
155+ /// will cause unnecessary runtime failures. Setting `length` to ``Length/unknown`` will trigger the upload
156+ /// to use `chunked` `Transfer-Encoding`, while using ``Length/known(_:)`` will use `Content-Length`.
157+ ///
158+ /// - parameters:
159+ /// - bytes: The bytes of the request body.
160+ /// - length: The length of the request body.
161+ @inlinable
162+ @preconcurrency
163+ public static func bytes< Bytes: Sequence & Sendable > (
164+ _ bytes: Bytes ,
165+ length: Length
166+ ) -> Self where Bytes. Element == UInt8 {
167+ Self . _bytes ( bytes, length: length)
168+ }
169+ #else
119170 /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `Sequence` of bytes.
120171 ///
121172 /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
@@ -137,6 +188,15 @@ extension HTTPClientRequest.Body {
137188 public static func bytes< Bytes: Sequence > (
138189 _ bytes: Bytes ,
139190 length: Length
191+ ) -> Self where Bytes. Element == UInt8 {
192+ Self . _bytes ( bytes, length: length)
193+ }
194+ #endif
195+
196+ @inlinable
197+ static func _bytes< Bytes: Sequence > (
198+ _ bytes: Bytes ,
199+ length: Length
140200 ) -> Self where Bytes. Element == UInt8 {
141201 self . init ( . sequence(
142202 length: length. storage,
@@ -151,6 +211,29 @@ extension HTTPClientRequest.Body {
151211 } )
152212 }
153213
214+ #if swift(>=5.6)
215+ /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `Collection` of bytes.
216+ ///
217+ /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
218+ /// usage of this construction will be double the size of the original collection. The construction
219+ /// of the `ByteBuffer` will be delayed until it's needed.
220+ ///
221+ /// Caution should be taken with this method to ensure that the `length` is correct. Incorrect lengths
222+ /// will cause unnecessary runtime failures. Setting `length` to ``Length/unknown`` will trigger the upload
223+ /// to use `chunked` `Transfer-Encoding`, while using ``Length/known(_:)`` will use `Content-Length`.
224+ ///
225+ /// - parameters:
226+ /// - bytes: The bytes of the request body.
227+ /// - length: The length of the request body.
228+ @inlinable
229+ @preconcurrency
230+ public static func bytes< Bytes: Collection & Sendable > (
231+ _ bytes: Bytes ,
232+ length: Length
233+ ) -> Self where Bytes. Element == UInt8 {
234+ Self . _bytes ( bytes, length: length)
235+ }
236+ #else
154237 /// Create an ``HTTPClientRequest/Body-swift.struct`` from a `Collection` of bytes.
155238 ///
156239 /// This construction will flatten the bytes into a `ByteBuffer`. As a result, the peak memory
@@ -168,6 +251,15 @@ extension HTTPClientRequest.Body {
168251 public static func bytes< Bytes: Collection > (
169252 _ bytes: Bytes ,
170253 length: Length
254+ ) -> Self where Bytes. Element == UInt8 {
255+ Self . _bytes ( bytes, length: length)
256+ }
257+ #endif
258+
259+ @inlinable
260+ static func _bytes< Bytes: Collection > (
261+ _ bytes: Bytes ,
262+ length: Length
171263 ) -> Self where Bytes. Element == UInt8 {
172264 self . init ( . sequence(
173265 length: length. storage,
@@ -182,6 +274,27 @@ extension HTTPClientRequest.Body {
182274 } )
183275 }
184276
277+ #if swift(>=5.6)
278+ /// Create an ``HTTPClientRequest/Body-swift.struct`` from an `AsyncSequence` of `ByteBuffer`s.
279+ ///
280+ /// This construction will stream the upload one `ByteBuffer` at a time.
281+ ///
282+ /// Caution should be taken with this method to ensure that the `length` is correct. Incorrect lengths
283+ /// will cause unnecessary runtime failures. Setting `length` to ``Length/unknown`` will trigger the upload
284+ /// to use `chunked` `Transfer-Encoding`, while using ``Length/known(_:)`` will use `Content-Length`.
285+ ///
286+ /// - parameters:
287+ /// - sequenceOfBytes: The bytes of the request body.
288+ /// - length: The length of the request body.
289+ @inlinable
290+ @preconcurrency
291+ public static func stream< SequenceOfBytes: AsyncSequence & Sendable > (
292+ _ sequenceOfBytes: SequenceOfBytes ,
293+ length: Length
294+ ) -> Self where SequenceOfBytes. Element == ByteBuffer {
295+ Self . _stream ( sequenceOfBytes, length: length)
296+ }
297+ #else
185298 /// Create an ``HTTPClientRequest/Body-swift.struct`` from an `AsyncSequence` of `ByteBuffer`s.
186299 ///
187300 /// This construction will stream the upload one `ByteBuffer` at a time.
@@ -197,6 +310,15 @@ extension HTTPClientRequest.Body {
197310 public static func stream< SequenceOfBytes: AsyncSequence > (
198311 _ sequenceOfBytes: SequenceOfBytes ,
199312 length: Length
313+ ) -> Self where SequenceOfBytes. Element == ByteBuffer {
314+ Self . _stream ( sequenceOfBytes, length: length)
315+ }
316+ #endif
317+
318+ @inlinable
319+ static func _stream< SequenceOfBytes: AsyncSequence > (
320+ _ sequenceOfBytes: SequenceOfBytes ,
321+ length: Length
200322 ) -> Self where SequenceOfBytes. Element == ByteBuffer {
201323 let body = self . init ( . asyncSequence( length: length. storage) {
202324 var iterator = sequenceOfBytes. makeAsyncIterator ( )
@@ -207,6 +329,29 @@ extension HTTPClientRequest.Body {
207329 return body
208330 }
209331
332+ #if swift(>=5.6)
333+ /// Create an ``HTTPClientRequest/Body-swift.struct`` from an `AsyncSequence` of bytes.
334+ ///
335+ /// This construction will consume 1kB chunks from the `Bytes` and send them at once. This optimizes for
336+ /// `AsyncSequence`s where larger chunks are buffered up and available without actually suspending, such
337+ /// as those provided by `FileHandle`.
338+ ///
339+ /// Caution should be taken with this method to ensure that the `length` is correct. Incorrect lengths
340+ /// will cause unnecessary runtime failures. Setting `length` to ``Length/unknown`` will trigger the upload
341+ /// to use `chunked` `Transfer-Encoding`, while using ``Length/known(_:)`` will use `Content-Length`.
342+ ///
343+ /// - parameters:
344+ /// - bytes: The bytes of the request body.
345+ /// - length: The length of the request body.
346+ @inlinable
347+ @preconcurrency
348+ public static func stream< Bytes: AsyncSequence & Sendable > (
349+ _ bytes: Bytes ,
350+ length: Length
351+ ) -> Self where Bytes. Element == UInt8 {
352+ Self . _stream ( bytes, length: length)
353+ }
354+ #else
210355 /// Create an ``HTTPClientRequest/Body-swift.struct`` from an `AsyncSequence` of bytes.
211356 ///
212357 /// This construction will consume 1kB chunks from the `Bytes` and send them at once. This optimizes for
@@ -224,6 +369,15 @@ extension HTTPClientRequest.Body {
224369 public static func stream< Bytes: AsyncSequence > (
225370 _ bytes: Bytes ,
226371 length: Length
372+ ) -> Self where Bytes. Element == UInt8 {
373+ Self . _stream ( bytes, length: length)
374+ }
375+ #endif
376+
377+ @inlinable
378+ static func _stream< Bytes: AsyncSequence > (
379+ _ bytes: Bytes ,
380+ length: Length
227381 ) -> Self where Bytes. Element == UInt8 {
228382 let body = self . init ( . asyncSequence( length: length. storage) {
229383 var iterator = bytes. makeAsyncIterator ( )
@@ -257,7 +411,7 @@ extension Optional where Wrapped == HTTPClientRequest.Body {
257411@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
258412extension HTTPClientRequest . Body {
259413 /// The length of a HTTP request body.
260- public struct Length {
414+ public struct Length : Sendable {
261415 /// The size of the request body is not known before starting the request
262416 public static let unknown : Self = . init( storage: . unknown)
263417
0 commit comments