Skip to content

Commit

Permalink
Fix is_connection_dropped with loads of useful contextual comments
Browse files Browse the repository at this point in the history
  • Loading branch information
florimondmanca committed Sep 15, 2019
1 parent fb95be2 commit 6af585a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
14 changes: 14 additions & 0 deletions httpx/concurrency/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ async def write(
raise WriteTimeout() from None

def is_connection_dropped(self) -> bool:
# Counter-intuitively, what we really want to know here is whether the socket is
# *readable*, i.e. whether it would return immediately with empty bytes if we
# called `.recv()` on it, indicating that the other end has closed the socket.
# See: https://github.com/encode/httpx/pull/143#issuecomment-515181778
#
# As it turns out, asyncio checks for readability in the background
# (see: https://github.com/encode/httpx/pull/276#discussion_r322000402),
# so checking for EOF or readability here would yield the same result.
#
# At the cost of rigour, we check for EOF instead of readability because asyncio
# does not expose any public API to check for readability.
# (For a solution that uses private asyncio APIs, see:
# https://github.com/encode/httpx/pull/143#issuecomment-515202982)

return self.stream_reader.at_eof()

async def close(self) -> None:
Expand Down
9 changes: 8 additions & 1 deletion httpx/concurrency/trio.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,19 @@ async def read(
raise ReadTimeout() from None

def is_connection_dropped(self) -> bool:
# Adapted from: https://github.com/encode/httpx/pull/143#issuecomment-515202982
stream = self.stream

# Peek through any SSLStream wrappers to get the underlying SocketStream.
while hasattr(stream, "transport_stream"):
stream = stream.transport_stream
assert isinstance(stream, trio.SocketStream)
return not stream.socket.is_readable()

# Counter-intuitively, what we really want to know here is whether the socket is
# *readable*, i.e. whether it would return immediately with empty bytes if we
# called `.recv()` on it, indicating that the other end has closed the socket.
# See: https://github.com/encode/httpx/pull/143#issuecomment-515181778
return stream.socket.is_readable()

def write_no_block(self, data: bytes) -> None:
self.write_buffer += data
Expand Down

0 comments on commit 6af585a

Please sign in to comment.