mirror of
https://github.com/borbann-platform/backend-api.git
synced 2025-12-18 12:14:05 +01:00
101 lines
3.4 KiB
Python
101 lines
3.4 KiB
Python
import logging
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI, HTTPException, Request
|
|
from fastapi.responses import JSONResponse
|
|
from app.core.config import settings
|
|
from app.api.v1.endpoints import api_router
|
|
from app.core.db import check_db_connection # Optional DB check
|
|
|
|
# --- Logging Configuration ---
|
|
# Basic config, consider more advanced setup (JSON, handlers) for production
|
|
logging.basicConfig(level=settings.LOG_LEVEL.upper(), format='%(levelname)s: %(name)s - %(message)s')
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# --- Lifespan Management ---
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Startup logic
|
|
logger.info("Application startup...")
|
|
# Example: Check DB connection (using dummy core.db function)
|
|
# if not await check_db_connection():
|
|
# logger.critical("Database connection failed on startup. Check config/connections.")
|
|
# Decide if this is fatal. In dummy mode, we probably continue.
|
|
# sys.exit(1) # Or raise RuntimeError
|
|
|
|
# Example: Placeholder for loading ML models, external resources, etc.
|
|
# app.state.ml_model = load_my_model()
|
|
logger.info("Dummy startup tasks complete.")
|
|
|
|
yield # Application runs here
|
|
|
|
# Shutdown logic
|
|
logger.info("Application shutdown...")
|
|
# Example: Clean up resources
|
|
# if hasattr(app.state, 'ml_model'):
|
|
# app.state.ml_model.cleanup()
|
|
# Optional: Dispose DB engine explicitly if needed (often handled by context managers)
|
|
# from app.core.db import engine
|
|
# if engine: await engine.dispose()
|
|
logger.info("Dummy shutdown tasks complete.")
|
|
|
|
|
|
# --- FastAPI Application Instance ---
|
|
app = FastAPI(
|
|
title=settings.PROJECT_NAME,
|
|
openapi_url=f"{settings.API_V1_STR}/openapi.json",
|
|
version="0.1.0", # Example version
|
|
description="Dummy API for Borbann Data Pipeline",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
|
|
# --- Global Exception Handler Example ---
|
|
@app.exception_handler(Exception)
|
|
async def generic_exception_handler(request: Request, exc: Exception):
|
|
# Log the full error internally
|
|
logger.error(f"Unhandled exception for request {request.url}: {exc}", exc_info=True)
|
|
# Return a generic error response to the client
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"detail": "An internal server error occurred."},
|
|
)
|
|
|
|
|
|
@app.exception_handler(HTTPException)
|
|
async def http_exception_handler(request: Request, exc: HTTPException):
|
|
# Default handler for FastAPI's own HTTPExceptions
|
|
# You might want to log these as well, depending on the status code
|
|
logger.warning(f"HTTP Exception: Status={exc.status_code}, Detail={exc.detail}")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content={"detail": exc.detail},
|
|
headers=exc.headers,
|
|
)
|
|
|
|
|
|
# --- Mount API Router ---
|
|
app.include_router(api_router, prefix=settings.API_V1_STR)
|
|
|
|
|
|
# --- Root Endpoint ---
|
|
@app.get("/", tags=["Root"], summary="Root endpoint")
|
|
async def read_root():
|
|
"""Simple root endpoint providing basic info."""
|
|
return {"message": f"Welcome to {settings.PROJECT_NAME} (Dummy Version)"}
|
|
|
|
|
|
# --- Middleware (Example: CORS) ---
|
|
# from fastapi.middleware.cors import CORSMiddleware
|
|
# origins = [
|
|
# "http://localhost:3000", # Allow frontend dev server
|
|
# # Add production frontend URL here
|
|
# ]
|
|
# app.add_middleware(
|
|
# CORSMiddleware,
|
|
# allow_origins=origins,
|
|
# allow_credentials=True,
|
|
# allow_methods=["*"],
|
|
# allow_headers=["*"],
|
|
# )
|