From ed8b7b2baf45eccd5339e4353950bb213053ec7e Mon Sep 17 00:00:00 2001 From: StarHeartHunt Date: Sun, 19 Apr 2026 19:53:19 +0800 Subject: [PATCH] :recycle: add default timeout --- nonebot/drivers/aiohttp.py | 7 ++++++ nonebot/drivers/websockets.py | 1 + nonebot/internal/driver/model.py | 2 +- tests/test_driver.py | 43 ++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/nonebot/drivers/aiohttp.py b/nonebot/drivers/aiohttp.py index dded8df0..8d907cd2 100644 --- a/nonebot/drivers/aiohttp.py +++ b/nonebot/drivers/aiohttp.py @@ -46,6 +46,7 @@ from nonebot.internal.driver import ( Timeout, TimeoutTypes, ) +from nonebot.log import logger from nonebot.utils import UNSET, UnsetType, exclude_unset try: @@ -328,6 +329,12 @@ class Mixin(HTTPClientMixin, WebSocketClientMixin): if setup.ping_interval is not UNSET: autoping = setup.ping_interval is not None + if isinstance(setup.timeout, Timeout) and setup.timeout.ping is not UNSET: + logger.warning( + "aiohttp driver does not expose a separate ping timeout; " + "the configured ping timeout will be ignored." + ) + async with aiohttp.ClientSession(version=version, trust_env=True) as session: async with session.ws_connect( setup.url, diff --git a/nonebot/drivers/websockets.py b/nonebot/drivers/websockets.py index 5de46c0d..0645e8ab 100644 --- a/nonebot/drivers/websockets.py +++ b/nonebot/drivers/websockets.py @@ -103,6 +103,7 @@ class Mixin(WebSocketClientMixin): { "open_timeout": open_timeout, "close_timeout": DEFAULT_TIMEOUT.close, + "ping_timeout": DEFAULT_TIMEOUT.ping, } ) diff --git a/nonebot/internal/driver/model.py b/nonebot/internal/driver/model.py index 3be5a0e2..e9e8f9c4 100644 --- a/nonebot/internal/driver/model.py +++ b/nonebot/internal/driver/model.py @@ -23,7 +23,7 @@ class Timeout: ping: float | None | UnsetType = UNSET -DEFAULT_TIMEOUT = Timeout(total=None, connect=5.0, read=30.0, close=10.0) +DEFAULT_TIMEOUT = Timeout(total=None, connect=5.0, read=30.0, close=10.0, ping=20.0) RawURL: TypeAlias = tuple[bytes, bytes, int | None, bytes] diff --git a/tests/test_driver.py b/tests/test_driver.py index 7b625035..2bd2897c 100644 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -878,6 +878,49 @@ async def test_websocket_client_timeout(driver: Driver, server_url: URL): await anyio.sleep(1) +@pytest.mark.anyio +@pytest.mark.parametrize( + "driver", + [ + pytest.param("nonebot.drivers.websockets:Driver", id="websockets"), + pytest.param("nonebot.drivers.aiohttp:Driver", id="aiohttp"), + ], + indirect=True, +) +async def test_websocket_client_ping_timeout(driver: Driver, server_url: URL): + """WebSocket connections work with different ping_timeout settings.""" + assert isinstance(driver, WebSocketClientMixin) + + ws_url = server_url.with_scheme("ws") + + # ping timeout not set (UNSET), falls back to DEFAULT_TIMEOUT.ping + request = Request("GET", ws_url, timeout=Timeout()) + async with driver.websocket(request) as ws: + await ws.send("quit") + with pytest.raises(WebSocketClosed): + await ws.receive() + + await anyio.sleep(1) + + # ping timeout explicitly set to None (disable ping timeout) + request = Request("GET", ws_url, timeout=Timeout(ping=None)) + async with driver.websocket(request) as ws: + await ws.send("quit") + with pytest.raises(WebSocketClosed): + await ws.receive() + + await anyio.sleep(1) + + # ping timeout set to a float value + request = Request("GET", ws_url, timeout=Timeout(ping=20.0)) + async with driver.websocket(request) as ws: + await ws.send("quit") + with pytest.raises(WebSocketClosed): + await ws.receive() + + await anyio.sleep(1) + + @pytest.mark.anyio @pytest.mark.parametrize( "driver",