bypass proxies for schedule API

This commit is contained in:
Server 2026-08-30 12:16:56 +00:00
parent 889eede593
commit bfbb8920e2

View file

@ -10,7 +10,7 @@ import time
from typing import Any from typing import Any
from urllib.error import HTTPError, URLError from urllib.error import HTTPError, URLError
from urllib.parse import quote from urllib.parse import quote
from urllib.request import Request, urlopen from urllib.request import ProxyHandler, Request, build_opener
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import config import config
@ -30,9 +30,11 @@ MOSCOW = ZoneInfo("Europe/Moscow")
_CACHE_TTL = 300.0 _CACHE_TTL = 300.0
_REQUEST_TIMEOUT = 10.0 _REQUEST_TIMEOUT = 10.0
_FAILURE_RETRY_DELAY = 30.0 _FAILURE_RETRY_DELAY = 30.0
_REQUEST_ATTEMPTS = 2
_cache: dict[str, tuple[float, list[dict[str, Any]]]] = {} _cache: dict[str, tuple[float, list[dict[str, Any]]]] = {}
_failures: dict[str, tuple[float, str]] = {} _failures: dict[str, tuple[float, str]] = {}
_cache_lock = threading.RLock() _cache_lock = threading.RLock()
_direct_opener = build_opener(ProxyHandler({}))
class ScheduleAPIError(RuntimeError): class ScheduleAPIError(RuntimeError):
@ -55,19 +57,32 @@ def _load_result(path: str) -> list[dict[str, Any]]:
return cached[1] return cached[1]
raise ScheduleAPIError(failure[1]) raise ScheduleAPIError(failure[1])
request = Request(_api_url(path), headers={"Accept": "application/json"}) url = _api_url(path)
request = Request(url, headers={"Accept": "application/json"})
error: Exception | None = None
payload: Any = None
for _ in range(_REQUEST_ATTEMPTS):
try: try:
with urlopen(request, timeout=_REQUEST_TIMEOUT) as response: with _direct_opener.open(request, timeout=_REQUEST_TIMEOUT) as response:
payload = json.load(response) payload = json.load(response)
except (HTTPError, URLError, TimeoutError, OSError, ValueError) as error: error = None
message = f"Не удалось получить {path}: {error}" break
except (HTTPError, URLError, TimeoutError, OSError, ValueError) as attempt_error:
error = attempt_error
if error is not None:
message = f"Не удалось получить {url}: {error}"
with _cache_lock: with _cache_lock:
_failures[path] = (now + _FAILURE_RETRY_DELAY, message) _failures[path] = (now + _FAILURE_RETRY_DELAY, message)
if cached: if cached:
return cached[1] return cached[1]
raise ScheduleAPIError(message) from error raise ScheduleAPIError(message) from error
if payload.get("ok") is not True or not isinstance(payload.get("result"), list): if (
not isinstance(payload, dict)
or payload.get("ok") is not True
or not isinstance(payload.get("result"), list)
):
if cached: if cached:
return cached[1] return cached[1]
raise ScheduleAPIError(f"Сервер вернул некорректный ответ для {path}") raise ScheduleAPIError(f"Сервер вернул некорректный ответ для {path}")