mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-12 01:04:35 +08:00
99 lines
2.8 KiB
Python
99 lines
2.8 KiB
Python
import json
|
|
from typing import Any, Awaitable, Callable
|
|
|
|
from fastapi import FastAPI, HTTPException, Request, Response
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app.api.apiv2_utils import OPENAPI_V2_PATH, V2ResponseMiddleware
|
|
from app.core.config import settings
|
|
from app.helper.locale import LocaleHelper
|
|
from app.startup.lifecycle import lifespan
|
|
from version import APP_VERSION
|
|
|
|
|
|
def _get_http_exception_message(detail: Any) -> str:
|
|
"""将 HTTPException 的 detail 转换为统一消息文本。"""
|
|
if isinstance(detail, str) and detail:
|
|
return detail
|
|
if detail is None:
|
|
return "请求失败"
|
|
try:
|
|
return json.dumps(detail, ensure_ascii=False)
|
|
except TypeError:
|
|
return str(detail)
|
|
|
|
|
|
async def localized_http_exception_handler(
|
|
_request: Request,
|
|
exc: HTTPException,
|
|
) -> JSONResponse:
|
|
"""
|
|
将 HTTPException 响应统一封装为 Response 结构并保留原始错误消息。
|
|
|
|
:param _request: 当前 HTTP 请求
|
|
:param exc: FastAPI HTTP 异常
|
|
:return: 统一 JSON 错误响应
|
|
"""
|
|
message = _get_http_exception_message(exc.detail)
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content={
|
|
"success": False,
|
|
"message": message,
|
|
"data": {},
|
|
},
|
|
headers=exc.headers,
|
|
)
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
"""
|
|
创建并配置 FastAPI 应用实例。
|
|
"""
|
|
_app = FastAPI(
|
|
title=settings.PROJECT_NAME,
|
|
version=APP_VERSION,
|
|
openapi_url=OPENAPI_V2_PATH,
|
|
lifespan=lifespan
|
|
)
|
|
|
|
@_app.get(f"{settings.API_V1_STR}/openapi.json", include_in_schema=False)
|
|
def get_v1_openapi_schema() -> dict[str, Any]:
|
|
"""保留旧版 OpenAPI 地址并返回当前完整接口文档。"""
|
|
return _app.openapi()
|
|
|
|
_app.add_exception_handler(HTTPException, localized_http_exception_handler)
|
|
|
|
# 配置 CORS 中间件
|
|
_app.add_middleware(
|
|
CORSMiddleware, # noqa
|
|
allow_origins=settings.ALLOWED_HOSTS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
_app.add_middleware(V2ResponseMiddleware)
|
|
|
|
@_app.middleware("http")
|
|
async def locale_context_middleware(
|
|
request: Request,
|
|
call_next: Callable[[Request], Awaitable[Response]],
|
|
) -> Response:
|
|
"""
|
|
为每个请求设置后端多语言上下文。
|
|
"""
|
|
token = LocaleHelper.set_current_locale(
|
|
LocaleHelper.get_locale_from_request(request)
|
|
)
|
|
try:
|
|
return await call_next(request)
|
|
finally:
|
|
LocaleHelper.reset_current_locale(token)
|
|
|
|
return _app
|
|
|
|
|
|
# 创建 FastAPI 应用实例
|
|
app = create_app()
|