173 lines
5.0 KiB
Python
173 lines
5.0 KiB
Python
"""
|
|
FastAPI 应用主文件
|
|
"""
|
|
import time
|
|
from fastapi import FastAPI, Request, status
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
from contextlib import asynccontextmanager
|
|
from app.core.config import settings
|
|
from app.core.response import error_response
|
|
from app.core.exceptions import BaseAPIException
|
|
from app.utils.logger import logger
|
|
from app.utils.monitor import api_monitor
|
|
from app.api.common.routes import router as common_router
|
|
from app.api.v1.inventory.routes import router as inventory_router
|
|
from app.api.v1.value.routes import router as value_router
|
|
from app.api.v1.delivery.routes import router as delivery_router
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""应用生命周期管理"""
|
|
# 启动时执行
|
|
logger.info("=" * 50)
|
|
logger.info(f"{settings.APP_NAME} 启动中...")
|
|
logger.info(f"版本: {settings.APP_VERSION}")
|
|
logger.info(f"调试模式: {settings.DEBUG}")
|
|
logger.info(f"环境变量: HOST={settings.HOST}, PORT={settings.PORT}")
|
|
logger.info("=" * 50)
|
|
|
|
yield
|
|
|
|
# 关闭时执行
|
|
logger.info(f"{settings.APP_NAME} 关闭中...")
|
|
|
|
|
|
# 创建 FastAPI 应用
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version=settings.APP_VERSION,
|
|
description="数据资产盘点系统后端 API 服务",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
openapi_url="/openapi.json",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# 配置 CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
# 添加监控中间件
|
|
@app.middleware("http")
|
|
async def monitoring_middleware(request: Request, call_next):
|
|
"""
|
|
监控中间件 - 记录所有 API 调用
|
|
|
|
Args:
|
|
request: 请求对象
|
|
call_next: 下一个中间件/路由处理器
|
|
|
|
Returns:
|
|
响应对象
|
|
"""
|
|
start_time = time.time()
|
|
endpoint = request.url.path
|
|
method = request.method
|
|
|
|
try:
|
|
# 调用下一个中间件/路由处理器
|
|
response = await call_next(request)
|
|
|
|
# 计算响应时间
|
|
response_time = (time.time() - start_time) * 1000 # 转换为毫秒
|
|
|
|
# 记录调用
|
|
api_monitor.record_call(
|
|
endpoint=endpoint,
|
|
method=method,
|
|
status_code=response.status_code,
|
|
response_time=response_time,
|
|
error=None
|
|
)
|
|
|
|
return response
|
|
|
|
except Exception as e:
|
|
# 计算响应时间
|
|
response_time = (time.time() - start_time) * 1000
|
|
|
|
# 记录调用(异常)
|
|
api_monitor.record_call(
|
|
endpoint=endpoint,
|
|
method=method,
|
|
status_code=500,
|
|
response_time=response_time,
|
|
error=str(e)
|
|
)
|
|
|
|
# 重新抛出异常,让全局异常处理器处理
|
|
raise
|
|
|
|
|
|
# 注册路由
|
|
app.include_router(common_router, prefix=settings.API_V1_PREFIX)
|
|
app.include_router(inventory_router, prefix=settings.API_V1_PREFIX)
|
|
app.include_router(value_router, prefix=settings.API_V1_PREFIX)
|
|
app.include_router(delivery_router, prefix=settings.API_V1_PREFIX)
|
|
|
|
|
|
# 异常处理器
|
|
@app.exception_handler(BaseAPIException)
|
|
async def base_api_exception_handler(request: Request, exc: BaseAPIException):
|
|
"""自定义 API 异常处理"""
|
|
logger.error(f"API 异常: {exc.message} | {exc.error_code}")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=error_response(
|
|
message=exc.message,
|
|
code=exc.status_code,
|
|
error_code=exc.error_code,
|
|
error_detail=exc.error_detail,
|
|
).dict(),
|
|
)
|
|
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
|
"""请求验证异常处理"""
|
|
logger.error(f"请求验证失败: {exc.errors()}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content=error_response(
|
|
message="请求参数验证失败",
|
|
code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
error_code="VALIDATION_ERROR",
|
|
error_detail=exc.errors(),
|
|
).dict(),
|
|
)
|
|
|
|
|
|
@app.exception_handler(Exception)
|
|
async def general_exception_handler(request: Request, exc: Exception):
|
|
"""通用异常处理"""
|
|
logger.exception(f"未处理的异常: {str(exc)}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content=error_response(
|
|
message="服务器内部错误",
|
|
code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
error_code="INTERNAL_SERVER_ERROR",
|
|
error_detail=str(exc) if settings.DEBUG else None,
|
|
).dict(),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host=settings.HOST,
|
|
port=settings.PORT,
|
|
reload=settings.DEBUG,
|
|
log_level=settings.LOG_LEVEL.lower(),
|
|
)
|