diff --git a/src/requests/adapters.py b/src/requests/adapters.py index eb240fa954..56a247477b 100644 --- a/src/requests/adapters.py +++ b/src/requests/adapters.py @@ -130,6 +130,7 @@ class HTTPAdapter(BaseAdapter): "_pool_connections", "_pool_maxsize", "_pool_block", + "urllib3_response_options", ] def __init__( @@ -154,6 +155,8 @@ def __init__( self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) + self.urllib3_response_options = {} + def __getstate__(self): return {attr: getattr(self, attr, None) for attr in self.__attrs__} @@ -435,6 +438,9 @@ def send( ): """Sends PreparedRequest object. Returns Response object. + It is possible to pass additional arguments to :meth:`urllib3.poolmanager.PoolManager.urlopen` + (e.g. `enforce_content_length`) by populating :attr:`HTTPAdapter.urllib3_response_options`. + :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send @@ -481,20 +487,25 @@ def send( else: timeout = TimeoutSauce(connect=timeout, read=timeout) + urlopen_kwargs = self.urllib3_response_options.copy() + urlopen_kwargs.update( + { + "method": request.method, + "url": url, + "body": request.body, + "headers": request.headers, + "redirect": False, + "assert_same_host": False, + "preload_content": False, + "decode_content": False, + "retries": self.max_retries, + "timeout": timeout, + "chunked": chunked, + } + ) + try: - resp = conn.urlopen( - method=request.method, - url=url, - body=request.body, - headers=request.headers, - redirect=False, - assert_same_host=False, - preload_content=False, - decode_content=False, - retries=self.max_retries, - timeout=timeout, - chunked=chunked, - ) + resp = conn.urlopen(**urlopen_kwargs) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request)