Recently, the ClientTransport protocol was updated to be in terms of HTTPBody, which is an AsyncSequence<ArraySlice<UInt8>>. Until now, the URLSession transport has buffered the request and response bodies in memory. This PR seeks to bring streaming support to recent Darwin platforms.
Modifications
On new enough Darwin platforms[^1], use URLSession delegate to perform bidirectional streaming with backpressure. Request body backpressure is provided by the use of StreamDelegate with a bound stream pair. Response body backpressure is provided by the use of AsyncBackpressuredStream which allows for a high and low watermark to suspend and resume the URLSession task.
[^1]: macOS 12, iOS 15, tvOS 15, watchOS 8
In more detail:
Vendor internal AsyncBackpressuredStream implementation from SE-0406.
Add HTTPBodyOutputStreamBridge which provides the OutputStreamDelegate required to bridge the AsyncSequence-based HTTPBody to an OutputStream.
Add BidirectionalStreamingURLSessionDelegate which makes use of HTTPBodyOutputStreamBridge for streaming request bodies and also uses the delegate callbacks to bridge the response body to HTTPBody.
Add URLSession.bidirectionalStreamingRequest(...) async throws, which provides a high-level URLSession-like API for setting up the appropriate URLSession task and delegate.
Add URLSession.bufferedRequest(...) async throws to provide a similar interfaces on platforms that don't support the streaming APIs on which we depend.
Add internal enum URLSessionTransport.Configuration.Implementation to control whether to use buffered or streaming implementation.
Detect appropriate implementation depending on the platform.
Result
On new enough Darwin platforms[^1], streaming will be used.
Test Plan
Add a set of tests that run with both buffered and streaming implementation on platforms that support streaming.
Add a set of tests that only run on platforms that support streaming, to test request flows only possible with streaming.
However, it's worth noting that our CI only runs on Linux, so we won't be testing the majority of this new feature in CI.
Motivation
Recently, the
ClientTransport
protocol was updated to be in terms ofHTTPBody
, which is anAsyncSequence<ArraySlice<UInt8>>
. Until now, the URLSession transport has buffered the request and response bodies in memory. This PR seeks to bring streaming support to recent Darwin platforms.Modifications
On new enough Darwin platforms[^1], use URLSession delegate to perform bidirectional streaming with backpressure. Request body backpressure is provided by the use of
StreamDelegate
with a bound stream pair. Response body backpressure is provided by the use ofAsyncBackpressuredStream
which allows for a high and low watermark to suspend and resume the URLSession task.[^1]: macOS 12, iOS 15, tvOS 15, watchOS 8
In more detail:
AsyncBackpressuredStream
implementation from SE-0406.HTTPBodyOutputStreamBridge
which provides theOutputStreamDelegate
required to bridge theAsyncSequence
-basedHTTPBody
to anOutputStream
.BidirectionalStreamingURLSessionDelegate
which makes use ofHTTPBodyOutputStreamBridge
for streaming request bodies and also uses the delegate callbacks to bridge the response body toHTTPBody
.URLSession.bidirectionalStreamingRequest(...) async throws
, which provides a high-level URLSession-like API for setting up the appropriate URLSession task and delegate.URLSession.bufferedRequest(...) async throws
to provide a similar interfaces on platforms that don't support the streaming APIs on which we depend.enum URLSessionTransport.Configuration.Implementation
to control whether to use buffered or streaming implementation.Result
Test Plan
However, it's worth noting that our CI only runs on Linux, so we won't be testing the majority of this new feature in CI.