abhisheksan's picture
Bump version to 1.0.0 and add HEAD health
21f2df3
"""Main FastAPI application for the multi-utility server."""
import time
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from app.core.config import settings
from app.core.logging import setup_logging, get_logger
from app.core.exceptions import MultiUtilityServerException
from app.middleware import APIKeyMiddleware, limiter
from app.apis.subtitles.router import router as subtitles_router
from app.apis.embeddings.router import router as embeddings_router
setup_logging()
logger = get_logger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan manager."""
logger.info("Starting multi-utility server...")
logger.info(f"Log level: {settings.log_level}")
logger.info(f"API keys configured: {len(settings.api_keys_set)}")
logger.info(f"CORS origins: {settings.cors_origins_list}")
yield
logger.info("Shutting down multi-utility server...")
app = FastAPI(
title="Multi-Utility Server",
description="Centralized FastAPI server providing reusable APIs for different projects",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan
)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins_list,
allow_credentials=True if settings.cors_origins else False,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
app.add_middleware(APIKeyMiddleware)
@app.exception_handler(MultiUtilityServerException)
async def custom_exception_handler(request: Request, exc: MultiUtilityServerException):
"""Handle custom application exceptions."""
logger.error(f"Application error: {exc.message}")
return JSONResponse(
status_code=exc.status_code,
content={"status": "error", "message": exc.message}
)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""Handle unexpected exceptions."""
logger.error(f"Unexpected error: {str(exc)}", exc_info=True)
return JSONResponse(
status_code=500,
content={"status": "error", "message": "An unexpected error occurred"}
)
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""Log all HTTP requests."""
start_time = time.time()
logger.info(f"Request: {request.method} {request.url.path}")
response = await call_next(request)
process_time = time.time() - start_time
logger.info(
f"Response: {response.status_code} | "
f"Time: {process_time:.4f}s | "
f"Path: {request.url.path}"
)
return response
@app.head("/health")
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {
"status": "healthy",
"service": "multi-utility-server",
"version": "1.0.0"
}
@app.get("/")
async def root():
"""Root endpoint with API information."""
return {
"message": "Multi-Utility FastAPI Server",
"version": "1.0.0",
"docs": "/docs",
"health": "/health",
"apis": {
"subtitles": "/api/v1/subtitles",
"embeddings": "/api/v1/embeddings"
}
}
app.include_router(subtitles_router)
app.include_router(embeddings_router)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.host,
port=settings.port,
reload=settings.reload,
log_level=settings.log_level.lower()
)