uxoxo/eb2ab
0
1"""2FastAPI application initialization with CORS and middleware.3"""4 5import os6from contextlib import asynccontextmanager7from fastapi import FastAPI, Request, status8from fastapi.middleware.cors import CORSMiddleware9from fastapi.responses import JSONResponse10from fastapi.exceptions import RequestValidationError11 12from api.routes import health, tts13from api.workers.tts_worker import start_worker14from api.storage import start_cleanup_thread15 16 17@asynccontextmanager18async def lifespan(app: FastAPI):19 """20 Application lifespan manager.21 22 Starts background workers on startup and performs cleanup on shutdown.23 """24 # Startup25 print("Starting FastAPI TTS API...")26 27 # Start TTS worker thread28 start_worker()29 30 # Start cleanup thread31 cleanup_interval = int(os.environ.get("CLEANUP_INTERVAL_SECONDS", "3600"))32 start_cleanup_thread(cleanup_interval)33 34 print("FastAPI TTS API started successfully")35 36 yield37 38 # Shutdown39 print("Shutting down FastAPI TTS API...")40 41 42def create_app() -> FastAPI:43 """44 Create and configure FastAPI application.45 46 Returns:47 Configured FastAPI app instance48 """49 # Create FastAPI app50 app = FastAPI(51 title="ebook2audiobook TTS API",52 description="REST API for Text-to-Speech conversion using ebook2audiobook engine",53 version="1.0.0",54 lifespan=lifespan,55 docs_url="/api/v1/docs",56 redoc_url="/api/v1/redoc",57 openapi_url="/api/v1/openapi.json"58 )59 60 # Configure CORS61 cors_origins = os.environ.get("CORS_ORIGINS", "").split(",")62 cors_origins = [origin.strip() for origin in cors_origins if origin.strip()]63 64 # If no origins configured, allow all (for development)65 if not cors_origins:66 cors_origins = ["*"]67 print("WARNING: CORS origins not configured. Allowing all origins.")68 69 app.add_middleware(70 CORSMiddleware,71 allow_origins=cors_origins,72 allow_credentials=True,73 allow_methods=["GET", "POST", "DELETE"],74 allow_headers=["Content-Type", "X-API-Key"],75 )76 77 # Include routers78 app.include_router(79 health.router,80 prefix="/api/v1",81 tags=["health"]82 )83 84 app.include_router(85 tts.router,86 prefix="/api/v1/tts",87 tags=["tts"]88 )89 90 # Custom exception handlers91 @app.exception_handler(RequestValidationError)92 async def validation_exception_handler(request: Request, exc: RequestValidationError):93 """Handle validation errors with detailed messages."""94 return JSONResponse(95 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,96 content={97 "error": "Validation error",98 "detail": exc.errors()99 }100 )101 102 @app.exception_handler(Exception)103 async def general_exception_handler(request: Request, exc: Exception):104 """Handle unexpected errors."""105 print(f"Unhandled exception: {exc}")106 return JSONResponse(107 status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,108 content={109 "error": "Internal server error",110 "detail": str(exc)111 }112 )113 114 # Root endpoint115 @app.get("/")116 async def root():117 """API root endpoint with basic information."""118 return {119 "service": "ebook2audiobook TTS API",120 "version": "1.0.0",121 "docs": "/api/v1/docs",122 "health": "/api/v1/health"123 }124 125 return app126 127 128# Create app instance129app = create_app()130 