@@ -174,13 +174,15 @@ def on_response(
174174 kind = FieldPosition .HEADER ,
175175 )
176176
177- self ._response_future .set_result (
178- AWSCRTHTTPResponse (
179- status = status_code ,
180- fields = fields ,
181- body = self ._body ,
182- )
177+ response = AWSCRTHTTPResponse (
178+ status = status_code ,
179+ fields = fields ,
180+ body = self ._body ,
183181 )
182+ if status_code != 200 and status_code >= 300 :
183+ self ._response_future .set_exception (CRTErrorResponse (response ))
184+ else :
185+ self ._response_future .set_result (response )
184186
185187 async def await_response (self ) -> AWSCRTHTTPResponse :
186188 return await asyncio .wrap_future (self ._response_future )
@@ -193,6 +195,18 @@ def _cancel(self, completion_future: ConcurrentFuture[int | Exception]) -> None:
193195 self ._response_future .cancel ()
194196
195197
198+ class CRTErrorResponse (Exception ):
199+ def __init__ (self , response : AWSCRTHTTPResponse ) -> None :
200+ self ._status = response .status
201+ self ._response = response
202+
203+ super ().__init__ (f"Request failed with status code { self ._status } " )
204+
205+ @property
206+ def response (self ) -> AWSCRTHTTPResponse :
207+ return self ._response
208+
209+
196210ConnectionPoolKey = tuple [str , str , int | None ]
197211ConnectionPoolDict = dict [ConnectionPoolKey , "crt_http.HttpClientConnection" ]
198212
@@ -251,7 +265,11 @@ async def send(
251265 crt_stream .completion_future .add_done_callback (
252266 partial (self ._close_input_body , body = crt_body )
253267 )
254- return await response_factory .await_response ()
268+ try :
269+ return await response_factory .await_response ()
270+ except CRTErrorResponse as e :
271+ await close (crt_body )
272+ return e .response
255273
256274 def _close_input_body (
257275 self , future : ConcurrentFuture [int ], * , body : "BufferableByteStream | BytesIO"
0 commit comments