0

Issue itself

During requests get(...).raw we are getting back a raw urllib3.HTTPResponse class. which is fine and intended to have, because of its IO capabilities. Considering that I don't really want to monkey-patch, is there a way to tell to this class that hey, look, I'm doing raw.read() which uses network for every iteration to avoid reading too much data at once from huge files, and so if during that time ECONNRESET comes from the server side, solve the connection and continue where it left?

The server side is external, aka non-manageable by me, only the client side.

I see no any possible way to have retry on this error, even with the urllib3's util.Retry class debugging the used libs themselves locally. Somewhat possibly similar trace-back and issue here: https://github.com/urllib3/urllib3/issues/1331

Code-sample to illustrate

import requests

raw = requests.get('http://httpbin.org/stream/20', stream=True).raw
while not line := raw.read(chunk_size=16):
  print line

Traceback:

Traceback (most recent call last):
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", 
  line 317, in recv_into
    return self.connection.recv_into(*args, **kwargs)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
    self._raise_ssl_error(self._ssl, result)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1614, in _raise_ssl_error
    raise WantReadError()
OpenSSL.SSL.WantReadError

During handling of the above exception, another exception occurred:Traceback (most recent call last):
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 317, in recv_into
    return self.connection.recv_into(*args, **kwargs)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
    self._raise_ssl_error(self._ssl, result)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1614, in _raise_ssl_error
    raise WantReadError()
OpenSSL.SSL.WantReadError

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 317, in recv_into
    return self.connection.recv_into(*args, **kwargs)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
    self._raise_ssl_error(self._ssl, result)
  File "/python3.8/site-packages/OpenSSL/SSL.py", line 1631, in _raise_ssl_error
    raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/python3.8/site-packages/urllib3/response.py", line 438, in _error_catcher
    yield
  File "/python3.8/site-packages/urllib3/response.py", line 519, in read
    data = self._fp.read(amt) if not fp_closed else b""
  File "/python3.8/http/client.py", line 455, in read
    n = self.readinto(b)
  File "/python3.8/http/client.py", line 499, in readinto
    n = self.fp.readinto(b)
  File "/python3.8/socket.py", line 669, in readinto
    return self._sock.recv_into(b)
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into
    return self.recv_into(*args, **kwargs)
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into
    return self.recv_into(*args, **kwargs)
  File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 322, in recv_into
    raise SocketError(str(e))
OSError: (104, 'ECONNRESET')

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/My-Code-Calls-With_Fancypath/file.py", line XYZ, in func_name
    ...
  File "/python3.8/site-packages/urllib3/response.py", line 541, in read
    raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
  File "/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/python3.8/site-packages/urllib3/response.py", line 455, in _error_catcher
    raise ProtocolError("Connection broken: %r" % e, e)


urllib3.exceptions.ProtocolError: ('Connection broken: OSError("(104, \'ECONNRESET\')")', OSError("(104, 'ECONNRESET')"))

Somewhat similar problem to my question is this one: Python Requests package: lost connection while streaming. The only difference is, that the accepted answer retries the whole download.

Env:

pyOpenSSL==18.0.0 urllib3==1.26.5 requests==2.25.1 python==3.8

Finally

Let's suppose theoretically this way is impossible. Do you have any good suggestions without changing MUCH the behaviour? Like using urllib3.HTTPResponse.iter_content(...) method (although its docs says NOT REENTRANT SAFE :( )?

0 Answers0