Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Sources/HTTPAPIs/Client/HTTPClientRequestBody+Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ public import struct Foundation.Data

@available(macOS 26.2, iOS 26.2, watchOS 26.2, tvOS 26.2, visionOS 26.2, *)
extension HTTPClientRequestBody where Writer: ~Copyable {
/// Creates a seekable request body from `Data`.
/// Creates a seekable request body from `Data` which does not require streaming.
///
/// - Parameter data: The data to send as the request body.
public static func data(_ data: Data) -> Self {
.seekable(knownLength: Int64(data.count)) { offset, writer in
var body = HTTPClientRequestBody.seekable(knownLength: Int64(data.count)) { offset, writer in
var writer = writer
try await writer.write(data.span.extracting(droppingFirst: Int(offset)))
return nil
}
body.requiresStreaming = false
return body
}
}
7 changes: 7 additions & 0 deletions Sources/HTTPAPIs/Client/HTTPClientRequestBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ where Writer.WriteElement == UInt8, Writer: SendableMetatype {
/// the `Content-Length` header field.
public let knownLength: Int64?

/// Whether the body has to be streamed, or can be collected into a buffer before sending.
///
/// An HTTPClient backend implementation that does not support request body streaming will
/// throw if the body requires streaming. Both `restartable` and `seekable` bodies require
/// streaming by default.
public var requiresStreaming: Bool = true

private enum WriteBody {
case restartable(@Sendable (consuming Writer) async throws -> HTTPFields?)
case seekable(@Sendable (Int64, consuming Writer) async throws -> HTTPFields?)
Expand Down