Rthur2003's picture
feat: fastAPI backend application entrypoint ile routers ve ara yazılım eklendi
e993aad
Raw History Blame Contribute Delete
4.01 kB
"""
CrownCode backend entrypoint with enhanced error handling.
"""
from __future__ import annotations
import asyncio
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from .routes.health import router as health_router
from .routes.youtube import router as youtube_router
from .routes.data_processing import router as data_processing_router
from .routes.analyze import router as analyze_router
from .routes.commend import router as commend_router
from .routes.reservations import router as reservations_router
from .routes.dreams import router as dreams_router
from .routes.remix import router as remix_router
from .services.logging_config import setup_logging, get_logger
setup_logging(level=os.getenv("LOG_LEVEL", "INFO"))
logger = get_logger(__name__)
def _load_origins() -> list[str]:
raw = os.getenv("CROWNCODE_CORS_ORIGINS") or os.getenv("CORS_ORIGIN") or "http://localhost:3000"
if raw.strip() == "*":
logger.warning(
"CORS wildcard '*' is not recommended for production. "
"Set CROWNCODE_CORS_ORIGINS to an explicit origin list."
)
return ["*"]
origins = [origin.strip() for origin in raw.split(",") if origin.strip()]
if not origins:
# No origins configured — default to localhost for development
origins = ["http://localhost:3000"]
logger.warning("No CORS origins configured, defaulting to localhost")
logger.info(f"CORS configured for origins: {origins}")
return origins
@asynccontextmanager
async def lifespan(_app: FastAPI):
# On the Space (AURIS_WARMUP=1 in the Dockerfile) load the models and
# compile librosa's numba code before the first visitor; off in tests.
warm_task = None
if os.getenv("AURIS_WARMUP") == "1":
from .routes.analyze import warm_up
warm_task = asyncio.create_task(warm_up())
yield
if warm_task is not None and not warm_task.done():
warm_task.cancel()
app = FastAPI(title="CrownCode Backend API", version="0.1.0", lifespan=lifespan)
@app.get("/")
async def root():
"""Root endpoint for health check and API info."""
return {
"name": "CrownCode Backend API",
"version": "0.1.0",
"status": "running",
"docs": "/docs",
"health": "/api/health"
}
@app.exception_handler(ValueError)
async def value_error_handler(request: Request, exc: ValueError) -> JSONResponse:
logger.warning(f"Validation error: {exc}")
return JSONResponse(
status_code=400,
content={"detail": str(exc), "type": "validation_error"}
)
@app.exception_handler(FileNotFoundError)
async def file_not_found_handler(request: Request, exc: FileNotFoundError) -> JSONResponse:
logger.error(f"File not found: {exc}")
return JSONResponse(
status_code=404,
content={"detail": "Resource not found", "type": "not_found"}
)
@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse:
logger.error(f"Unhandled exception: {type(exc).__name__}: {exc}", exc_info=True)
return JSONResponse(
status_code=500,
content={"detail": "Internal server error", "type": "server_error"}
)
_origins = _load_origins()
app.add_middleware(
CORSMiddleware,
allow_origins=_origins,
allow_credentials="*" not in _origins,
allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Accept"],
expose_headers=["X-Remix-Analysis", "X-Multitrack-Analysis"],
)
app.include_router(health_router)
app.include_router(youtube_router)
app.include_router(data_processing_router)
app.include_router(analyze_router)
app.include_router(commend_router)
app.include_router(reservations_router)
app.include_router(dreams_router)
app.include_router(remix_router)
logger.info("CrownCode backend API initialized")