diff --git a/backend/common/exception/exception_handler.py b/backend/common/exception/exception_handler.py index 502c0fab..2df46e5b 100644 --- a/backend/common/exception/exception_handler.py +++ b/backend/common/exception/exception_handler.py @@ -4,7 +4,6 @@ from fastapi import FastAPI, Request from fastapi.exceptions import RequestValidationError from pydantic import ValidationError from starlette.exceptions import HTTPException -from starlette.middleware.cors import CORSMiddleware from uvicorn.protocols.http.h11_impl import STATUS_PHRASES from backend.common.exception.errors import BaseExceptionMixin @@ -193,66 +192,8 @@ def register_exception(app: FastAPI): else: res = response_base.fail(res=CustomResponseCode.HTTP_500) content = res.model_dump() - request.state.__request_all_unknown_exception__ = content content.update(trace_id=get_request_trace_id(request)) return MsgSpecJSONResponse( status_code=StandardResponseCode.HTTP_500, content=content, ) - - if settings.MIDDLEWARE_CORS: - - @app.exception_handler(StandardResponseCode.HTTP_500) - async def cors_custom_code_500_exception_handler(request, exc): - """ - 跨域自定义 500 异常处理 - - `Related issue `_ - - `Solution `_ - - :param request: FastAPI 请求对象 - :param exc: 自定义异常 - :return: - """ - if isinstance(exc, BaseExceptionMixin): - content = { - 'code': exc.code, - 'msg': exc.msg, - 'data': exc.data, - } - else: - if settings.ENVIRONMENT == 'dev': - content = { - 'code': StandardResponseCode.HTTP_500, - 'msg': str(exc), - 'data': None, - } - else: - res = response_base.fail(res=CustomResponseCode.HTTP_500) - content = res.model_dump() - request.state.__request_cors_500_exception__ = content - content.update(trace_id=get_request_trace_id(request)) - response = MsgSpecJSONResponse( - status_code=exc.code if isinstance(exc, BaseExceptionMixin) else StandardResponseCode.HTTP_500, - content=content, - background=exc.background if isinstance(exc, BaseExceptionMixin) else None, - ) - origin = request.headers.get('origin') - if origin: - cors = CORSMiddleware( - app=app, - allow_origins=settings.CORS_ALLOWED_ORIGINS, - allow_credentials=True, - allow_methods=['*'], - allow_headers=['*'], - expose_headers=settings.CORS_EXPOSE_HEADERS, - ) - response.headers.update(cors.simple_headers) - has_cookie = 'cookie' in request.headers - if cors.allow_all_origins and has_cookie: - response.headers['Access-Control-Allow-Origin'] = origin - elif not cors.allow_all_origins and cors.is_allowed_origin(origin=origin): - response.headers['Access-Control-Allow-Origin'] = origin - response.headers.add_vary_header('Origin') - return response diff --git a/backend/core/registrar.py b/backend/core/registrar.py index 5a38e48d..7913fbc7 100644 --- a/backend/core/registrar.py +++ b/backend/core/registrar.py @@ -13,7 +13,9 @@ from fastapi import Depends, FastAPI from fastapi_limiter import FastAPILimiter from fastapi_pagination import add_pagination from starlette.middleware.authentication import AuthenticationMiddleware +from starlette.middleware.cors import CORSMiddleware from starlette.staticfiles import StaticFiles +from starlette.types import ASGIApp from backend.common.exception.exception_handler import register_exception from backend.common.log import set_custom_logfile, setup_logging @@ -65,7 +67,23 @@ async def register_init(app: FastAPI) -> AsyncGenerator[None, None]: def register_app() -> FastAPI: """注册 FastAPI 应用""" - app = FastAPI( + + class MyFastAPI(FastAPI): + if settings.MIDDLEWARE_CORS: + # Related issues + # https://github.com/fastapi/fastapi/discussions/7847 + # https://github.com/fastapi/fastapi/discussions/8027 + def build_middleware_stack(self) -> ASGIApp: + return CORSMiddleware( + super().build_middleware_stack(), + allow_origins=settings.CORS_ALLOWED_ORIGINS, + allow_credentials=True, + allow_methods=['*'], + allow_headers=['*'], + expose_headers=settings.CORS_EXPOSE_HEADERS, + ) + + app = MyFastAPI( title=settings.FASTAPI_TITLE, version=settings.FASTAPI_VERSION, description=settings.FASTAPI_DESCRIPTION, @@ -134,19 +152,6 @@ def register_middleware(app: FastAPI) -> None: # I18n app.add_middleware(I18nMiddleware) - # CORS - if settings.MIDDLEWARE_CORS: - from fastapi.middleware.cors import CORSMiddleware - - app.add_middleware( - CORSMiddleware, - allow_origins=settings.CORS_ALLOWED_ORIGINS, - allow_credentials=True, - allow_methods=['*'], - allow_headers=['*'], - expose_headers=settings.CORS_EXPOSE_HEADERS, - ) - # Access log app.add_middleware(AccessMiddleware)