Repository navigation
HTTP/2 connection implementation is currently flaky. #80
Copy link
Copy link
Closed
Description
Is it me ?
Or the simplest test fails:
httpcore.Client().get("https://www.google.com")
outputs:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/httpcore/concurrency.py", line 65, in read
self.stream_reader.read(n), timeout.read_timeout
File "/usr/lib/python3.7/asyncio/tasks.py", line 423, in wait_for
raise futures.TimeoutError()
concurrent.futures._base.TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/connection_pool.py", line 114, in send
request, stream=stream, ssl=ssl, timeout=timeout
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/connection.py", line 53, in send
request, stream=stream, timeout=timeout
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/http2.py", line 77, in send
await response.read()
File "/usr/local/lib/python3.7/dist-packages/httpcore/models.py", line 684, in read
self._content = b"".join([part async for part in self.stream()])
File "/usr/local/lib/python3.7/dist-packages/httpcore/models.py", line 684, in <listcomp>
self._content = b"".join([part async for part in self.stream()])
File "/usr/local/lib/python3.7/dist-packages/httpcore/models.py", line 695, in stream
async for chunk in self.raw():
File "/usr/local/lib/python3.7/dist-packages/httpcore/models.py", line 712, in raw
async for part in self._raw_stream:
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/http2.py", line 121, in body_iter
event = await self.receive_event(stream_id, timeout)
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/http2.py", line 131, in receive_event
data = await self.reader.read(self.READ_NUM_BYTES, timeout)
File "/usr/local/lib/python3.7/dist-packages/httpcore/concurrency.py", line 68, in read
raise ReadTimeout()
httpcore.exceptions.ReadTimeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/manatlan/Bureau/reqman/reqman.py", line 1414, in <module>
httpcore.Client().get("https://www.google.com")
File "/usr/local/lib/python3.7/dist-packages/httpcore/client.py", line 496, in get
timeout=timeout,
File "/usr/local/lib/python3.7/dist-packages/httpcore/client.py", line 472, in request
timeout=timeout,
File "/usr/local/lib/python3.7/dist-packages/httpcore/client.py", line 665, in send
timeout=timeout,
File "/usr/lib/python3.7/asyncio/base_events.py", line 573, in run_until_complete
return future.result()
File "/usr/local/lib/python3.7/dist-packages/httpcore/client.py", line 287, in send
allow_redirects=allow_redirects,
File "/usr/local/lib/python3.7/dist-packages/httpcore/client.py", line 313, in send_handling_redirects
request, stream=stream, ssl=ssl, timeout=timeout
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/connection_pool.py", line 117, in send
self.active_connections.remove(connection)
File "/usr/local/lib/python3.7/dist-packages/httpcore/dispatch/connection_pool.py", line 64, in remove
del self.all[connection]
KeyError: <httpcore.dispatch.connection.HTTPConnection object at 0x7fadbf88e0f0>
btw, I can't catch the Exception ?!
try:
httpcore.Client().get("https://www.google.com")
except concurrent.futures._base.TimeoutError:
print(1)
except httpcore.exceptions.ReadTimeout:
print(2)
Metadata
Metadata
Assignees
Labels
No labels
Activity
yeraydiazdiaz commentedon May 25, 2019
Thanks for the report. TL;DR Google is using HTTP2 and returning a 400 error which creates an unexpected content which causes the ReadTimeout. I've tried with other URLs and it seems to work correctly.
Looking deeper there are few things happening:
content = self.body_iter(stream_id), which is then passed to the response.await response.read()thebody_iterattempts to read events from the stream and yield data, however theStreamResetis the last event of the stream which is unhandled in the loop, so it attempts to read a new event from the stream and times out.ReadTimeoutexception is caught in thetry..exceptand closes the response in the finally block, theReadTimeoutbubbles upConnectionPool.sendmethod also has atry..exceptblock which catches the timeout exception and attempts to remove the connection there, but the connection has already been removed onresponse.closeso aKeyErroris raised.I'll see if I can put together a couple of PRs for these issues.
lovelydinosaur commentedon May 25, 2019
Thanks folks. I should be able to review this on Tuesday.
lovelydinosaur commentedon May 25, 2019
Something that’d be really useful for us with debugging would be configuration on the client to determine which HTTP protocols should be supported. Then if we get something like this we can easily narrow it down to eg. “Is this an issue in the HTTP/2 implementation”
lovelydinosaur commentedon May 25, 2019
It's specifically an issue with HTTP/2 (doesn't reproduce if I switch the connection to force HTTP/1). Doesn't reproduce on all sites (eg. I'd be testing against the HTTP/2 implementation against
https://www.example.com.)[-]httpcore.Client().get("https://www.google.com") doesn't work[/-][+]HTTP/2 connection implementation is currently flaky.[/+]manatlan commentedon May 26, 2019
thanks in advance ...
I will use httpcore in https://github.com/manatlan/reqman ...
Hope you release a httpcore on pypi with cookies soon
lovelydinosaur commentedon May 28, 2019
Now resolved in master.
manatlan commentedon May 28, 2019
great, thanks !
Are you planning to release a pypi version with this fix ?
akjanik commentedon Jun 6, 2019
@tomchristie I am trying to use the lib with Google Cloud services which use HTTP/2 and got hit by that, while trying to authenticate to
https://www.googleapis.com/oauth2/v4/tokenInstalling from git resolves the problem, would be it possible to do (minor?) release anytime soon?lovelydinosaur commentedon Jun 6, 2019
Gotcha. Released as 0.3.1. 👍