From 5727a8346b0a9e84c8777d1b61dcf44d31da9589 Mon Sep 17 00:00:00 2001 From: Jan Fryauf Date: Fri, 2 Oct 2026 12:06:19 +0200 Subject: [PATCH] Add default timeout to all API requests Requests were sent without a timeout, so a connection that stops responding blocked update_data() forever. Apply a default (10, 30) s timeout through a Session subclass and lower urllib3 retries from 20 to 5 so a hung request fails within minutes. --- ThermiaOnlineAPI/api/ThermiaAPI.py | 15 +++++++++++++-- ThermiaOnlineAPI/tests/setup.py | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ThermiaOnlineAPI/api/ThermiaAPI.py b/ThermiaOnlineAPI/api/ThermiaAPI.py index a4a450f..3b3059e 100644 --- a/ThermiaOnlineAPI/api/ThermiaAPI.py +++ b/ThermiaOnlineAPI/api/ThermiaAPI.py @@ -48,6 +48,17 @@ # Fix for multiple operation modes with the same value REG_OPERATIONMODE_SKIP_VALUES = ["REG_VALUE_OPERATION_MODE_SERVICE"] +# Default (connect, read) timeout in seconds for every request +DEFAULT_REQUEST_TIMEOUT = (10, 30) + + +class ThermiaSession(requests.Session): + """Session that applies a default timeout to every request.""" + + def request(self, *args, **kwargs): + kwargs.setdefault("timeout", DEFAULT_REQUEST_TIMEOUT) + return super().request(*args, **kwargs) + class ThermiaAPI: def __init__(self, email, password): @@ -65,9 +76,9 @@ def __init__(self, email, password): "Access-Control-Allow-Origin": "*", } - self.__session = requests.Session() + self.__session = ThermiaSession() retry = Retry( - total=20, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504] + total=5, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) self.__session.mount("https://", adapter) diff --git a/ThermiaOnlineAPI/tests/setup.py b/ThermiaOnlineAPI/tests/setup.py index b60f281..4b8d092 100644 --- a/ThermiaOnlineAPI/tests/setup.py +++ b/ThermiaOnlineAPI/tests/setup.py @@ -10,6 +10,7 @@ AZURE_AUTH_CONFIRM_URL, AZURE_AUTH_GET_TOKEN_URL, AZURE_SELF_ASSERTED_URL, + DEFAULT_REQUEST_TIMEOUT, ) from ..const import THERMIA_CONFIG_URL from ..model.HeatPump import ThermiaHeatPump @@ -130,4 +131,9 @@ def setup_thermia_and_perform_basic_tests( heat_pump.operational_status_pid == expected_operational_status_pid_value ), f"Operational status PID - expected: {expected_operational_status_pid_value}, got: {heat_pump.operational_status_pid}" + request_timeouts = [request.timeout for request in requests_mock.request_history] + assert all( + timeout == DEFAULT_REQUEST_TIMEOUT for timeout in request_timeouts + ), f"Request timeouts - expected: {DEFAULT_REQUEST_TIMEOUT}, got: {request_timeouts}" + return heat_pump