|
1 | 1 | import asyncio |
| 2 | +import socket |
2 | 3 | from ssl import SSLContext |
3 | 4 | from typing import Optional |
4 | 5 |
|
|
13 | 14 | map_exceptions, |
14 | 15 | ) |
15 | 16 | from .._types import TimeoutDict |
| 17 | +from .._utils import is_socket_readable |
16 | 18 | from .base import AsyncBackend, AsyncLock, AsyncSemaphore, AsyncSocketStream |
17 | 19 |
|
18 | 20 | SSL_MONKEY_PATCH_APPLIED = False |
@@ -171,21 +173,10 @@ async def aclose(self) -> None: |
171 | 173 | with map_exceptions({OSError: CloseError}): |
172 | 174 | self.stream_writer.close() |
173 | 175 |
|
174 | | - def is_connection_dropped(self) -> bool: |
175 | | - # Counter-intuitively, what we really want to know here is whether the socket is |
176 | | - # *readable*, i.e. whether it would return immediately with empty bytes if we |
177 | | - # called `.recv()` on it, indicating that the other end has closed the socket. |
178 | | - # See: https://github.com/encode/httpx/pull/143#issuecomment-515181778 |
179 | | - # |
180 | | - # As it turns out, asyncio checks for readability in the background |
181 | | - # (see: https://github.com/encode/httpx/pull/276#discussion_r322000402), |
182 | | - # so checking for EOF or readability here would yield the same result. |
183 | | - # |
184 | | - # At the cost of rigour, we check for EOF instead of readability because asyncio |
185 | | - # does not expose any public API to check for readability. |
186 | | - # (For a solution that uses private asyncio APIs, see: |
187 | | - # https://github.com/encode/httpx/pull/143#issuecomment-515202982) |
188 | | - return self.stream_reader.at_eof() |
| 176 | + def is_readable(self) -> bool: |
| 177 | + transport = self.stream_reader._transport # type: ignore |
| 178 | + sock: socket.socket = transport.get_extra_info("socket") |
| 179 | + return is_socket_readable(sock.fileno()) |
189 | 180 |
|
190 | 181 |
|
191 | 182 | class Lock(AsyncLock): |
|
0 commit comments