Files
mini-erp/mini-backend/core/api_gateway.py
T
GeorgeandClaude Sonnet 5 ab3c613165 Initial commit: mini-erp (backend FastAPI + frontend React/Vite)
Base para el flujo de ramas por cliente.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 10:34:12 -05:00

131 lines
4.2 KiB
Python

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