| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- """
- __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
|