Skip to content

Commit fe51447

Browse files
bitcoin3usRichard Taylorclaude
authored
Fix DownloadManager timeout kwarg compatibility with desktop aiohttp (#107)
* Fix DownloadManager timeout kwarg compatibility with desktop aiohttp The desktop aiohttp implementation doesn't support the timeout keyword argument added in #98. Fall back to calling session.get() without timeout when TypeError is raised, so downloads work on both ESP32 (with timeout) and desktop (without). Fixes test_custom_headers and test_json_download failures on desktop builds. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * Add connection timeout support to aiohttp and restore in DownloadManager The MicroPython aiohttp library had no timeout support (marked as TODO). Add a timeout parameter to request_raw(), _request(), and request() that wraps asyncio.open_connection() with asyncio.wait_for(). This allows DownloadManager to use session.get(timeout=...) to prevent connections from hanging indefinitely on stalled TCP/TLS handshakes, which was the original fix in #98. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --------- Co-authored-by: Richard Taylor <[email protected]> Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
1 parent e91e7f4 commit fe51447

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

internal_filesystem/lib/aiohttp/__init__.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ async def __aenter__(self):
109109
async def __aexit__(self, *args):
110110
return await asyncio.sleep(0)
111111

112-
# TODO: Implement timeouts
112+
# Connection timeout is supported via the timeout parameter on request methods
113113

114-
async def _request(self, method, url, data=None, json=None, ssl=None, params=None, headers={}):
114+
async def _request(self, method, url, data=None, json=None, ssl=None, params=None, headers={}, timeout=None):
115115
redir_cnt = 0
116116
while redir_cnt < 2:
117-
reader = await self.request_raw(method, url, data, json, ssl, params, headers)
117+
reader = await self.request_raw(method, url, data, json, ssl, params, headers, timeout=timeout)
118118
_headers = []
119119
sline = await reader.readline()
120120
sline = sline.split(None, 2)
@@ -167,6 +167,7 @@ async def request_raw(
167167
headers={},
168168
is_handshake=False,
169169
version=None,
170+
timeout=None,
170171
):
171172
if json and isinstance(json, dict):
172173
data = _json.dumps(json)
@@ -193,7 +194,12 @@ async def request_raw(
193194
host, port = host.split(":", 1)
194195
port = int(port)
195196

196-
reader, writer = await asyncio.open_connection(host, port, ssl=ssl)
197+
if timeout is not None:
198+
reader, writer = await asyncio.wait_for(
199+
asyncio.open_connection(host, port, ssl=ssl), timeout
200+
)
201+
else:
202+
reader, writer = await asyncio.open_connection(host, port, ssl=ssl)
197203

198204
# Use protocol 1.0, because 1.1 always allows to use chunked transfer-encoding
199205
# But explicitly set Connection: close, even though this should be default for 1.0,
@@ -232,7 +238,7 @@ async def request_raw(
232238
await writer.awrite(query)
233239
return reader, writer
234240

235-
def request(self, method, url, data=None, json=None, ssl=None, params=None, headers={}):
241+
def request(self, method, url, data=None, json=None, ssl=None, params=None, headers={}, timeout=None):
236242
return _RequestContextManager(
237243
self,
238244
self._request(
@@ -243,6 +249,7 @@ def request(self, method, url, data=None, json=None, ssl=None, params=None, head
243249
ssl=ssl,
244250
params=params,
245251
headers=dict(**self._base_headers, **headers),
252+
timeout=timeout,
246253
),
247254
)
248255

0 commit comments

Comments
 (0)