# +====================================================================== # | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ] # +---------------------------------------------------------------------- # | Copyright (c) 2021-2026 一米阳光团队 版权所有 # | 开源协议: Apache-2.0 # +====================================================================== # 由 apps/__init__.py 迁移而来。 """应用工厂:create_app 组装中间件、路由、异常处理与 lifespan。""" import time from fastapi import FastAPI from fastapi.exceptions import RequestValidationError from fastapi.logger import logger from starlette.requests import Request from starlette.responses import JSONResponse from config.app import FASTAPI_DEBUG from core.exceptions import AuthorizationException, BusinessException from core.middleware import ( register_middleware, register_cros, db_session_middleware, operation_log_middleware, ) from core.redis_client import redis_lifespan, redis_middleware from routers import register_router def create_app() -> FastAPI: app = FastAPI( title="FastAPI", description="FastAPI", version="v1", lifespan=redis_lifespan, ) # 注册跨域中间件 register_cros(app) # 注册Redis上下文注入中间件(先注册→内层:先注入Redis再开DB会话) app.middleware("http")(redis_middleware) # 注册数据库会话中间件(后注册→外层:DB会话包裹业务逻辑,finally保证关闭) app.middleware("http")(db_session_middleware) # 注册操作日志中间件(在DB会话内层,记录写操作日志) app.middleware("http")(operation_log_middleware) # 注册路由 register_router(app) # 登录检测 register_middleware(app) # 注册全局异常处理 register_exception(app) # 请求计时(最后注册→最外层,统计完整耗时) @app.middleware("http") async def add_process_time_header(request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(round(process_time, 5)) if FASTAPI_DEBUG: logger.info(f"访问记录:{request.method} url:{request.url} 耗时:{str(round(process_time, 5))}") return response return app # 注册全局异常处理 def register_exception(app: FastAPI): """全局异常捕获。""" @app.exception_handler(AuthorizationException) async def unicorn_exception_handler(request: Request, exc: AuthorizationException): return JSONResponse( status_code=200, content={"code": exc.code, "data": None, "msg": exc.msg, "ok": False}, ) @app.exception_handler(BusinessException) async def business_exception_handler(request: Request, exc: BusinessException): return JSONResponse( status_code=200, content={"code": exc.code, "data": None, "msg": exc.msg, "ok": False}, ) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): errors = [] for err in exc.errors(): field = err.get("loc", [""])[-1] msg = err.get("msg", "") if field and field != "body": errors.append(f"{field}: {msg}") else: errors.append(msg) return JSONResponse( status_code=200, content={"code": 1, "data": None, "msg": "/".join(errors)}, )