@@ -224,6 +224,7 @@ def __call__(
224224 )
225225
226226 except Exception as e :
227+ _drain_request_body (environ )
227228 return self ._handle_error (e , ctx , start_response )
228229
229230 def _handle_unary (
@@ -468,12 +469,13 @@ def _handle_stream(
468469 # been called in time. So we return the response stream as a separate generator
469470 # function. This means some duplication of error handling.
470471 return _response_stream (
471- first_response , response_stream , writer , send_trailers , ctx
472+ first_response , environ , response_stream , writer , send_trailers , ctx
472473 )
473474 except Exception as e :
474475 # Exception before any response message was returned. An error after the first
475476 # response message will be handled by _response_stream, so here we have a
476477 # full error-only response.
478+ _drain_request_body (environ )
477479 _send_stream_response_headers (
478480 start_response , protocol , codec , resp_compression .name (), ctx
479481 )
@@ -554,21 +556,13 @@ def _request_stream(
554556 read_max_bytes : int | None = None ,
555557) -> Iterator [_REQ ]:
556558 reader = EnvelopeReader (request_class , codec , compression , read_max_bytes )
557- try :
558- for chunk in _read_body (environ ):
559- yield from reader .feed (chunk )
560- except ConnectError :
561- if environ .get ("SERVER_PROTOCOL" , "" ).startswith ("HTTP/1" ):
562- # In HTTP/1, the request body should be drained before returning. Generally it's
563- # best for the application server to handle this, but gunicorn is a famous
564- # server that doesn't do so, so we go ahead and do it ourselves.
565- for _ in _read_body (environ ):
566- pass
567- raise
559+ for chunk in _read_body (environ ):
560+ yield from reader .feed (chunk )
568561
569562
570563def _response_stream (
571564 first_response : _RES ,
565+ environ : WSGIEnvironment ,
572566 response_stream : Iterator [_RES ],
573567 writer : EnvelopeWriter ,
574568 send_trailers : Callable [[list [tuple [str , str ]]], None ] | None ,
@@ -583,6 +577,7 @@ def _response_stream(
583577 yield body
584578 except Exception as e :
585579 error = e
580+ _drain_request_body (environ )
586581
587582 yield _end_response (
588583 writer .end (
@@ -638,3 +633,12 @@ def _apply_interceptors(
638633 continue
639634 func = functools .partial (interceptor .intercept_bidi_stream_sync , func )
640635 return replace (endpoint , function = func )
636+
637+
638+ def _drain_request_body (environ : WSGIEnvironment ) -> None :
639+ if environ .get ("SERVER_PROTOCOL" , "" ).startswith ("HTTP/1" ):
640+ # In HTTP/1, the request body should be drained before returning. Generally it's
641+ # best for the application server to handle this, but gunicorn is a famous
642+ # server that doesn't do so, so we go ahead and do it ourselves.
643+ for _ in _read_body (environ ):
644+ pass
0 commit comments