bypass proxies for schedule API
This commit is contained in:
parent
889eede593
commit
bfbb8920e2
1 changed files with 23 additions and 8 deletions
|
|
@ -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}")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue