from dotenv import load_dotenv import logging import requests from requests import Session from typing import Optional, Dict, Any import os from fastapi import HTTPException import urllib3 load_dotenv(dotenv_path=".env") APIGATEWAY_URL = os.getenv("APIGATEWAY_URL", "") APIGATEWAY_USER = os.getenv("APIGATEWAY_USER", "") APIGATEWAY_PASSWORD = os.getenv("APIGATEWAY_PASSWORD", "") APIGATEWAY_COMPANYDB = os.getenv("APIGATEWAY_COMPANYDB", "") APIGATEWAY_DBINSTANCE = os.getenv("APIGATEWAY_DBINSTANCE", "") APIGATEWAY_TIMEOUT = float(os.getenv("APIGATEWAY_TIMEOUT", 30.0)) logger = logging.getLogger(__name__) api_gateway_session: Optional[Session] = None def ensure_api_gateway_session(force_refresh: bool = False) -> Session: global api_gateway_session if api_gateway_session and not force_refresh: return api_gateway_session logger.info("Iniciando sesión en APIGateway...") login_url = f"{APIGATEWAY_URL}/login" payload = { "CompanyDB": APIGATEWAY_COMPANYDB, "UserName": APIGATEWAY_USER, "Password": APIGATEWAY_PASSWORD, "DBInstance": APIGATEWAY_DBINSTANCE, } try: session = Session() session.verify = False response = session.post( login_url, json=payload, timeout=APIGATEWAY_TIMEOUT, ) if response.status_code != 200: logger.error(f"Error login APIGateway. Status: {response.status_code}") raise HTTPException( status_code=response.status_code, detail="Error de autenticación con APIGateway" ) api_gateway_session = session logger.info(f"Sesión APIGateway establecida. Cookies: {dict(session.cookies)}") return session except requests.RequestException as exc: logger.error(f"Error de conexión con APIGateway: {exc}") api_gateway_session = None raise HTTPException( status_code=500, detail=f"No se pudo conectar con APIGateway: {exc}" ) def forward_to_api_gateway( method: str, endpoint: str, params: Optional[Dict[str, Any]] = None, json_data: Optional[Any] = None, ) -> requests.Response: if not method or not endpoint: raise ValueError("method y endpoint son requeridos") method = method.upper() session = ensure_api_gateway_session() url_destino = f"{APIGATEWAY_URL}/{endpoint}" log_extra = {"http_method": method, "endpoint": endpoint} logger.info(f"[APIGateway] [{method}] {endpoint}", extra=log_extra) try: response = session.request( method=method, url=url_destino, params=params, json=json_data, timeout=APIGATEWAY_TIMEOUT, ) except requests.exceptions.Timeout: logger.error(f"Timeout ({APIGATEWAY_TIMEOUT}s) en APIGateway {endpoint}", extra=log_extra) raise ConnectionError(f"Timeout al conectar con APIGateway: {endpoint}") except requests.RequestException as exc: logger.error(f"Error en solicitud APIGateway: {exc}", extra=log_extra) raise ConnectionError(f"Error en solicitud APIGateway: {exc}") if response.status_code == 401: logger.warning("Sesión APIGateway expirada (401). Reautenticando...", extra=log_extra) session = ensure_api_gateway_session(force_refresh=True) try: response = session.request( method=method, url=url_destino, params=params, json=json_data, timeout=APIGATEWAY_TIMEOUT, ) except requests.RequestException as exc: raise ConnectionError(f"Error en reintento APIGateway: {exc}") if response.status_code >= 400: error_msg = response.text[:500] logger.error( f"[{response.status_code}] APIGateway {endpoint}: {error_msg}", extra={**log_extra, "status_code": response.status_code} ) raise HTTPException( status_code=response.status_code, detail=f"Error en APIGateway: {error_msg}" ) logger.info( f"[{response.status_code}] APIGateway {endpoint}", extra={**log_extra, "status_code": response.status_code} ) return response