""" __init__.py - auther: tanlie date: 2026/8/30 """ import logging import traceback from fastapi import FastAPI, Request, HTTPException from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from app.mobile import register_mobile_routes from app.core.response import error_response # Basic logging configuration for the app; applications may override this logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s") logger = logging.getLogger("app") def create_app(): app = FastAPI() register_mobile_routes(app) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): # Build a friendly, JSON-serializable summary of validation errors errors = [] for e in exc.errors(): loc = e.get("loc", []) # remove leading location indicators like 'body', 'query', 'path', 'header' if loc and len(loc) > 0 and str(loc[0]) in ("body", "query", "path", "header"): loc_parts = loc[1:] else: loc_parts = loc # join remaining location parts into a dotted path for readability loc_str = ".".join([str(p) for p in loc_parts if p is not None]) if loc_parts else "" errors.append({"field": loc_str, "message": e.get("msg", "")}) # Log validation details for debugging logger.info("Validation error for %s: %s", request.url.path, errors) return JSONResponse( status_code=422, content=error_response(msg="参数校验失败", code=422, data=errors), ) @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): # Use HTTPException's status_code and detail detail = exc.detail if exc.detail is not None else "" logger.warning("HTTPException for %s: %s", request.url.path, detail) return JSONResponse( status_code=getattr(exc, "status_code", 500), content=error_response(msg=str(detail), code=getattr(exc, "status_code", 500)), ) @app.exception_handler(Exception) async def generic_exception_handler(request: Request, exc: Exception): # Map common ValueError to a friendlier 400 parameter error if isinstance(exc, ValueError): # Log with stack for debugging tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)) logger.warning("ValueError on %s: %s\n%s", request.url.path, str(exc), tb) return JSONResponse( status_code=400, content=error_response(msg=str(exc) or "参数错误", code=400), ) # Generic fallback to avoid leaking internal stack traces # Log full stack trace for internal debugging tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)) logger.error("Unhandled exception on %s: %s\n%s", request.url.path, str(exc), tb) return JSONResponse( status_code=500, content=error_response(msg="服务器内部错误", code=500), ) return app