factuges-document-signing-s.../src/signing_service/main.py

135 lines
4.0 KiB
Python
Raw Normal View History

from contextlib import asynccontextmanager
2026-02-10 12:39:18 +00:00
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
2026-01-22 10:37:35 +00:00
from dotenv import load_dotenv
2026-01-29 17:35:43 +00:00
from pathlib import Path
from datetime import datetime, UTC
2026-01-29 17:35:43 +00:00
from dateutil import tz
2026-01-22 10:37:35 +00:00
from signing_service.application.settings.container import get_settings
2026-01-29 17:35:43 +00:00
from signing_service.application.settings.setup_logger import create_logger
from signing_service.api.routes.sign_document import router as sign_router
2026-02-03 15:23:25 +00:00
from signing_service.application.settings.version import get_package_version
2026-01-22 10:37:35 +00:00
load_dotenv()
# 👇 FAIL FAST: load settings at startup
2026-01-29 17:35:43 +00:00
settings = get_settings()
version = get_package_version()
def build_logger():
"""Crea el logger de aplicación y asegura el directorio de logs."""
log_dir = Path(settings.state_path)
log_dir.mkdir(parents=True, exist_ok=True)
app_logger = create_logger(
name="factuges-document-signing-service",
log_path=log_dir / "factuges-document-signing-service.log",
)
app_logger.info("")
app_logger.info(
"============================================================")
app_logger.info("FactuGES Document Signing Service - START")
app_logger.info("Version: %s", version)
app_logger.info("UTC Now: %s", datetime.now(UTC).isoformat())
app_logger.info("Environment: %s", settings.app_env)
app_logger.info("")
app_logger.info("Log Level: %s", settings.log_level)
app_logger.info(
"Log: %s",
log_dir / "factuges-document-signing-service.log",
)
app_logger.info("")
app_logger.info("Secret Provider: %s", settings.secret_provider)
app_logger.info("Infisical project ID: %s", settings.infisical_project_id)
app_logger.info("Infisical environment: %s", settings.infisical_env_slug)
app_logger.info("")
return app_logger
logger = build_logger()
2026-01-22 10:37:35 +00:00
2026-02-10 12:39:18 +00:00
async def http_exception_handler(request: Request, exc: HTTPException):
"""Registra y devuelve errores HTTP controlados."""
2026-02-10 12:39:18 +00:00
logger.error(
"HTTPException %s %s | status=%s | detail=%s",
request.method,
request.url.path,
exc.status_code,
exc.detail,
)
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)
class LoggingMiddleware(BaseHTTPMiddleware):
"""Registra request y response para trazabilidad básica."""
2026-02-10 12:39:18 +00:00
async def dispatch(self, request: Request, call_next):
client_ip = request.client.host if request.client else "unknown"
2026-02-10 12:39:18 +00:00
method = request.method
url = request.url.path
logger.info("Request: %s %s from %s", method, url, client_ip)
2026-02-10 12:39:18 +00:00
response = await call_next(request)
logger.info(
"Response: %s %s returned %s to %s",
method,
url,
response.status_code,
client_ip,
)
2026-02-10 12:39:18 +00:00
return response
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Gestiona el ciclo de vida de la aplicación."""
logger.info("Starting signing service")
yield
logger.info("Stopping signing service")
async def healthcheck() -> dict[str, str]:
"""Endpoint simple de healthcheck."""
return {"status": "ok"}
2026-02-10 12:39:18 +00:00
async def get_version() -> dict[str, str]:
"""Devuelve la versión publicada del servicio."""
return {"version": version}
2026-02-10 12:39:18 +00:00
def create_app() -> FastAPI:
app = FastAPI(lifespan=lifespan,
title="FactuGES Document Signing Service",
version=version)
2026-02-10 12:39:18 +00:00
app.add_exception_handler(HTTPException, http_exception_handler)
app.add_middleware(LoggingMiddleware)
app.include_router(sign_router)
logger.info("API routes registered from sign_document router")
2026-01-29 17:35:43 +00:00
app.add_api_route("/health", healthcheck, methods=["GET"])
logger.info("Health check endpoint registered at /health")
2026-01-29 17:35:43 +00:00
app.add_api_route("/version", get_version, methods=["GET"])
logger.info("Version endpoint registered at /version")
return app
2026-01-22 10:37:35 +00:00
2026-02-03 15:23:25 +00:00
app = create_app()