@@ -140,7 +140,7 @@ extension Converter {
140
140
/// - Throws: An error if setting the request body as binary fails.
141
141
public func setOptionalRequestBodyAsBinary( _ value: HTTPBody ? , headerFields: inout HTTPFields , contentType: String )
142
142
throws -> HTTPBody ?
143
- { try setOptionalRequestBody ( value, headerFields: & headerFields, contentType: contentType, convert: { $0 } ) }
143
+ { setOptionalRequestBody ( value, headerFields: & headerFields, contentType: contentType, convert: { $0 } ) }
144
144
145
145
/// Sets a required request body as binary in the specified header fields and returns an `HTTPBody`.
146
146
///
@@ -154,7 +154,7 @@ extension Converter {
154
154
/// - Throws: An error if setting the request body as binary fails.
155
155
public func setRequiredRequestBodyAsBinary( _ value: HTTPBody , headerFields: inout HTTPFields , contentType: String )
156
156
throws -> HTTPBody
157
- { try setRequiredRequestBody ( value, headerFields: & headerFields, contentType: contentType, convert: { $0 } ) }
157
+ { setRequiredRequestBody ( value, headerFields: & headerFields, contentType: contentType, convert: { $0 } ) }
158
158
159
159
/// Sets an optional request body as URL-encoded form data in the specified header fields and returns an `HTTPBody`.
160
160
///
@@ -202,6 +202,56 @@ extension Converter {
202
202
)
203
203
}
204
204
205
+ /// Sets a required request body as multipart and returns the streaming body.
206
+ ///
207
+ /// - Parameters:
208
+ /// - value: The multipart body to be set as the request body.
209
+ /// - headerFields: The header fields in which to set the content type.
210
+ /// - contentType: The content type to be set in the header fields.
211
+ /// - allowsUnknownParts: A Boolean value indicating whether parts with unknown names
212
+ /// should be pass through. If `false`, encountering an unknown part throws an error
213
+ /// whent the returned body sequence iterates it.
214
+ /// - requiredExactlyOncePartNames: The list of part names that are required exactly once.
215
+ /// - requiredAtLeastOncePartNames: The list of part names that are required at least once.
216
+ /// - atMostOncePartNames: The list of part names that can appear at most once.
217
+ /// - zeroOrMoreTimesPartNames: The list of names that can appear any number of times.
218
+ /// - encode: A closure that transforms the type-safe part into a raw part.
219
+ /// - Returns: A streaming body representing the multipart-encoded request body.
220
+ /// - Throws: Currently never, but might in the future.
221
+ public func setRequiredRequestBodyAsMultipart< Part: Sendable > (
222
+ _ value: MultipartBody < Part > ,
223
+ headerFields: inout HTTPFields ,
224
+ contentType: String ,
225
+ allowsUnknownParts: Bool ,
226
+ requiredExactlyOncePartNames: Set < String > ,
227
+ requiredAtLeastOncePartNames: Set < String > ,
228
+ atMostOncePartNames: Set < String > ,
229
+ zeroOrMoreTimesPartNames: Set < String > ,
230
+ encoding encode: @escaping @Sendable ( Part) throws -> MultipartRawPart
231
+ ) throws -> HTTPBody {
232
+ let boundary = configuration. multipartBoundaryGenerator. makeBoundary ( )
233
+ let contentTypeWithBoundary = contentType + " ; boundary= \( boundary) "
234
+ return setRequiredRequestBody (
235
+ value,
236
+ headerFields: & headerFields,
237
+ contentType: contentTypeWithBoundary,
238
+ convert: { value in
239
+ convertMultipartToBytes (
240
+ value,
241
+ requirements: . init(
242
+ allowsUnknownParts: allowsUnknownParts,
243
+ requiredExactlyOncePartNames: requiredExactlyOncePartNames,
244
+ requiredAtLeastOncePartNames: requiredAtLeastOncePartNames,
245
+ atMostOncePartNames: atMostOncePartNames,
246
+ zeroOrMoreTimesPartNames: zeroOrMoreTimesPartNames
247
+ ) ,
248
+ boundary: boundary,
249
+ encode: encode
250
+ )
251
+ }
252
+ )
253
+ }
254
+
205
255
/// Retrieves the response body as JSON and transforms it into a specified type.
206
256
///
207
257
/// - Parameters:
@@ -244,4 +294,48 @@ extension Converter {
244
294
guard let data else { throw RuntimeError . missingRequiredResponseBody }
245
295
return try getResponseBody ( type, from: data, transforming: transform, convert: { $0 } )
246
296
}
297
+ /// Returns an async sequence of multipart parts parsed from the provided body stream.
298
+ ///
299
+ /// - Parameters:
300
+ /// - type: The type representing the type-safe multipart body.
301
+ /// - data: The HTTP body data to transform.
302
+ /// - transform: A closure that transforms the multipart body into the output type.
303
+ /// - boundary: The multipart boundary string.
304
+ /// - allowsUnknownParts: A Boolean value indicating whether parts with unknown names
305
+ /// should be pass through. If `false`, encountering an unknown part throws an error
306
+ /// whent the returned body sequence iterates it.
307
+ /// - requiredExactlyOncePartNames: The list of part names that are required exactly once.
308
+ /// - requiredAtLeastOncePartNames: The list of part names that are required at least once.
309
+ /// - atMostOncePartNames: The list of part names that can appear at most once.
310
+ /// - zeroOrMoreTimesPartNames: The list of names that can appear any number of times.
311
+ /// - decoder: A closure that parses a raw part into a type-safe part.
312
+ /// - Returns: A value of the output type.
313
+ /// - Throws: If the transform closure throws.
314
+ public func getResponseBodyAsMultipart< C, Part: Sendable > (
315
+ _ type: MultipartBody < Part > . Type ,
316
+ from data: HTTPBody ? ,
317
+ transforming transform: @escaping @Sendable ( MultipartBody < Part > ) throws -> C ,
318
+ boundary: String ,
319
+ allowsUnknownParts: Bool ,
320
+ requiredExactlyOncePartNames: Set < String > ,
321
+ requiredAtLeastOncePartNames: Set < String > ,
322
+ atMostOncePartNames: Set < String > ,
323
+ zeroOrMoreTimesPartNames: Set < String > ,
324
+ decoding decoder: @escaping @Sendable ( MultipartRawPart) async throws -> Part
325
+ ) throws -> C {
326
+ guard let data else { throw RuntimeError . missingRequiredResponseBody }
327
+ let multipart = convertBytesToMultipart (
328
+ data,
329
+ boundary: boundary,
330
+ requirements: . init(
331
+ allowsUnknownParts: allowsUnknownParts,
332
+ requiredExactlyOncePartNames: requiredExactlyOncePartNames,
333
+ requiredAtLeastOncePartNames: requiredAtLeastOncePartNames,
334
+ atMostOncePartNames: atMostOncePartNames,
335
+ zeroOrMoreTimesPartNames: zeroOrMoreTimesPartNames
336
+ ) ,
337
+ transform: decoder
338
+ )
339
+ return try transform ( multipart)
340
+ }
247
341
}
0 commit comments