Validate Transport Support For Bidirectional Streaming#717
Open
jonathan343 wants to merge 1 commit into
Open
Conversation
Most Python HTTP clients cannot read response data while the request body is still being written, so bidirectional event stream operations fail mid-stream with an opaque connection error. Transports must now opt in by setting SUPPORTS_DUPLEX_STREAMING to True, and RequestPipeline.duplex_stream fails fast with UnsupportedTransportError when the configured transport does not declare support. AWSCRTHTTPClient and MockHTTPClient declare support; AIOHTTPClient explicitly does not.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Problem
Only the AWS CRT HTTP client can perform true bidirectional (duplex) streaming in the Python ecosystem, since interleaving request and response data in practice requires HTTP/2. Code generation already defaults services with event streams to
AWSCRTHTTPClient, but nothing stops a user from overridingconfig.transportwithAIOHTTPClientor a custom transport that can't do this. When they then invoke a bidirectional operation, the request is sent and the stream appears to hang until it eventually dies with an error such as:smithy_core.exceptions.SmithyError: Server disconnectedNothing in that error points at the actual problem (the configured transport), so this is painful to debug.
Solution
This PR makes duplex support an explicit, opt-in transport capability. A new
SUPPORTS_DUPLEX_STREAMINGclass attribute onClientTransportdefaults toFalse, andRequestPipeline.duplex_streamnow fails fast with an actionableUnsupportedTransportErrorbefore any request work happens.AWSCRTHTTPClientdeclares support,AIOHTTPClientexplicitly does not (it buffers the full response before returning and aiohttp has no HTTP/2 support).Example
Invoking a bidirectional operation with a non-duplex transport, with this PR:
Without this PR: the request is sent, the stream stalls, and eventually fails mid-stream with
SmithyError: Server disconnected.With this PR: the call fails immediately, before anything is sent:
Why opt-in rather than opt-out? A survey of the Python HTTP client landscape shows most clients cannot interleave request and response data, so absence of a declaration is treated as "not supported". The pipeline reads the attribute with
getattr(transport, "SUPPORTS_DUPLEX_STREAMING", False), so existing custom transports that predate the attribute keep working for everything except duplex operations, which were already broken for them.Why fail at call time instead of client construction? A non-duplex transport is perfectly valid for every other operation on the same client. The capability is only required when a duplex operation is actually invoked, so that is where validation happens.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.