"""FastAPI 应用入口。 创建应用实例、配置 CORS 中间件、注册全局异常处理器、挂载 API 路由。 启动命令: uvicorn backend.app.main:app --reload """ import logging import traceback from fastapi import FastAPI from fastapi import Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from pathlib import Path from backend.app.api.routes import api_router from backend.app.core.config import get_settings from backend.app.core.exceptions import AppException logger = logging.getLogger(__name__) settings = get_settings() app = FastAPI(title=settings.app_name) # 配置 CORS 跨域,允许前端开发服务器访问 app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.exception_handler(AppException) async def app_exception_handler(_: Request, exc: AppException) -> JSONResponse: """全局捕获 AppException,返回统一的错误 JSON 格式。 避免每个路由重复构造错误响应,所有业务异常由此处理器统一格式化。 """ # 统一业务异常返回格式,避免每个接口重复构造错误响应。 return JSONResponse( status_code=exc.status_code, content={ "code": exc.code, "message": exc.message, "data": {}, }, ) @app.exception_handler(Exception) async def unhandled_exception_handler(_: Request, exc: Exception) -> JSONResponse: """捕获所有未处理异常,记录完整 traceback 到日志并返回 500。 避免 FastAPI 默认的 bare 500 响应,让运维能从日志中定位问题。 """ logger.error("Unhandled exception: %s\n%s", exc, traceback.format_exc()) return JSONResponse( status_code=500, content={ "code": 500, "message": f"服务器内部错误: {type(exc).__name__}: {exc}", "data": {}, }, ) # 挂载所有 API 路由,路由前缀在 router.py 中统一定义 app.include_router(api_router) # 挂载本地上传文件目录为静态文件服务(开发环境用) _local_upload_dir = Path("D:/tmp/order-flow-oss/local-uploads") _local_upload_dir.mkdir(parents=True, exist_ok=True) app.mount("/uploads", StaticFiles(directory=str(_local_upload_dir)), name="local-uploads")