59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
"""Shared `httpx.Client` helper.
|
|
|
|
Creating short-lived httpx clients disables connection pooling and costs extra CPU.
|
|
This module provides a small singleton client for callers that just need basic
|
|
GETs without the full HTTPClient wrapper.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from typing import Dict, Optional
|
|
|
|
import httpx
|
|
|
|
from API.ssl_certs import resolve_verify_value
|
|
|
|
_DEFAULT_USER_AGENT = (
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0 Safari/537.36"
|
|
)
|
|
|
|
_lock = threading.Lock()
|
|
_shared_client: Optional[httpx.Client] = None
|
|
|
|
|
|
def get_shared_httpx_client(
|
|
*,
|
|
timeout: float = 30.0,
|
|
verify_ssl: bool = True,
|
|
headers: Optional[Dict[str, str]] = None,
|
|
) -> httpx.Client:
|
|
"""Return a process-wide shared synchronous httpx.Client."""
|
|
|
|
global _shared_client
|
|
if _shared_client is None:
|
|
with _lock:
|
|
if _shared_client is None:
|
|
base_headers = {"User-Agent": _DEFAULT_USER_AGENT}
|
|
if headers:
|
|
base_headers.update({str(k): str(v) for k, v in headers.items()})
|
|
_shared_client = httpx.Client(
|
|
timeout=timeout,
|
|
verify=resolve_verify_value(verify_ssl),
|
|
headers=base_headers,
|
|
)
|
|
|
|
return _shared_client
|
|
|
|
|
|
def close_shared_httpx_client() -> None:
|
|
global _shared_client
|
|
client = _shared_client
|
|
_shared_client = None
|
|
if client is not None:
|
|
try:
|
|
client.close()
|
|
except Exception:
|
|
pass
|