# ================================================================ # services/data/app/external/base_client.py # ================================================================ """Base HTTP client for external APIs""" import httpx from typing import Dict, Any, Optional import structlog from datetime import datetime logger = structlog.get_logger() class BaseAPIClient: def __init__(self, base_url: str, api_key: Optional[str] = None): self.base_url = base_url self.api_key = api_key self.timeout = httpx.Timeout(30.0) async def _get(self, endpoint: str, params: Optional[Dict] = None, headers: Optional[Dict] = None) -> Optional[Dict[str, Any]]: """Make GET request""" try: url = f"{self.base_url}{endpoint}" # Add API key to headers if available request_headers = headers or {} if self.api_key: request_headers["Authorization"] = f"Bearer {self.api_key}" async with httpx.AsyncClient(timeout=self.timeout) as client: response = await client.get(url, params=params, headers=request_headers) response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: logger.error("HTTP error", status_code=e.response.status_code, url=url) return None except httpx.RequestError as e: logger.error("Request error", error=str(e), url=url) return None except Exception as e: logger.error("Unexpected error", error=str(e), url=url) return None async def _post(self, endpoint: str, data: Optional[Dict] = None, headers: Optional[Dict] = None) -> Optional[Dict[str, Any]]: """Make POST request""" try: url = f"{self.base_url}{endpoint}" request_headers = headers or {} if self.api_key: request_headers["Authorization"] = f"Bearer {self.api_key}" async with httpx.AsyncClient(timeout=self.timeout) as client: response = await client.post(url, json=data, headers=request_headers) response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: logger.error("HTTP error", status_code=e.response.status_code, url=url) return None except httpx.RequestError as e: logger.error("Request error", error=str(e), url=url) return None except Exception as e: logger.error("Unexpected error", error=str(e), url=url) return None