66from smithy_core .codecs import Codec
77from smithy_core .deserializers import DeserializeableShape
88from smithy_core .documents import TypeRegistry
9+ from smithy_core .exceptions import ExpectationNotMetException
910from smithy_core .interfaces import Endpoint , TypedProperties , URI
1011from smithy_core .schemas import APIOperation
1112from smithy_core .serializers import SerializeableShape
@@ -43,8 +44,8 @@ class HttpBindingClientProtocol(HttpClientProtocol):
4344 """An HTTP-based protocol that uses HTTP binding traits."""
4445
4546 @property
46- def codec (self ) -> Codec :
47- """The codec used for the serde of input and output shapes ."""
47+ def payload_codec (self ) -> Codec :
48+ """The codec used for the serde of input and output payloads ."""
4849 ...
4950
5051 @property
@@ -63,20 +64,23 @@ def serialize_request[
6364 endpoint : URI ,
6465 context : TypedProperties ,
6566 ) -> HTTPRequest :
66- # TODO: request binding cache like done in SJ
67+ # TODO(optimization) : request binding cache like done in SJ
6768 serializer = HTTPRequestSerializer (
68- payload_codec = self .codec ,
69- http_trait = operation .schema .expect_trait (HTTPTrait ), # TODO
69+ payload_codec = self .payload_codec ,
70+ http_trait = operation .schema .expect_trait (HTTPTrait ),
7071 endpoint_trait = operation .schema .get_trait (EndpointTrait ),
7172 )
7273
73- input .serialize (serializer = serializer )
74+ input .serialize (
75+ serializer = serializer
76+ ) # TODO: ensure serializer adds content-type
7477 request = serializer .result
7578
7679 if request is None :
77- raise ValueError ("Request is None" ) # TODO
80+ raise ExpectationNotMetException (
81+ "Expected request to be serialized, but was None"
82+ )
7883
79- request .fields ["content-type" ].add (self .content_type )
8084 return request
8185
8286 async def deserialize_response [
@@ -96,15 +100,17 @@ async def deserialize_response[
96100 raise NotImplementedError
97101
98102 body = response .body
99- # TODO: extract to utility, seems common
100- if (read := getattr (body , "read" , None )) is not None and iscoroutinefunction (
101- read
102- ):
103- body = BytesIO (await read ())
104103
105- # TODO: response binding cache like done in SJ
104+ # if body is not streaming and is async, we have to buffer it
105+ if not operation .output_stream_member :
106+ if (
107+ read := getattr (body , "read" , None )
108+ ) is not None and iscoroutinefunction (read ):
109+ body = BytesIO (await read ())
110+
111+ # TODO(optimization): response binding cache like done in SJ
106112 deserializer = HTTPResponseDeserializer (
107- payload_codec = self .codec ,
113+ payload_codec = self .payload_codec ,
108114 http_trait = operation .schema .expect_trait (HTTPTrait ),
109115 response = response ,
110116 body = body , # type: ignore
0 commit comments