Rthur2003's picture
fix: improve CORS origin handling with warnings for production and defaults for development
dd0b28c
"""
CrownCode backend entrypoint with enhanced error handling.
"""
from __future__ import annotations
import os
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 .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
app = FastAPI(title="CrownCode Backend API", version="0.1.0")
@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,
# credentials=True is only safe with an explicit origin list, not wildcard
allow_credentials="*" not in _origins,
allow_methods=["*"],
allow_headers=["*"],
)
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)
logger.info("CrownCode backend API initialized")