fastapi: 多个子应用时判断全局异常的处理形式

一,代码

场景:

fastapi项目下面有两个子应用,一个是api: 接口站,另一个是admin:管理后台,
api接口站,处理异常后返回json,
admin.管理后台,有传统的页面请求也有ajax方式访问,
要求非ajax时,返回到一个错误信息页面,
ajax访问时,当然是返回json

代码:

# 返回异常信息,根据子应用和是否ajax分别进行处理,管理后非ajax请求,跳到错误页面
def response_exception(request: Request,err_data):
    path = request.url.path

    # --- 状况 A:如果是 API 子应用的请求,一律返回 JSON ---
    if path.startswith("/api"):
        return JSONResponse(
            status_code=err_data['status_code'],
            content={"data": {}, "msg": err_data['detail'], "code": err_data['status_code']}
        )

    # --- 状况 B:如果是 Admin 子应用的请求,需要分情况讨论 ---
    elif path.startswith("/admin"):
        accept_header = request.headers.get("accept", "")
        requested_with = request.headers.get("x-requested-with", "")

        # 判断是否为 Ajax 请求:
        # 1. 检查 X-Requested-With 是否为 XMLHttpRequest (传统 Ajax)
        # 2. 或者检查 Accept 头是否更倾向于接收 JSON (现代 fetch/axios 请求)
        is_ajax = (
                requested_with.lower() == "xmlhttprequest" or
                ("application/json" in accept_header and "text/html" not in accept_header)
        )
        if is_ajax:
            # 管理后台的 Ajax 请求出错 -> 返回 JSON 方便前端弹窗提示(如 ElementUI/AntDesign)
            return JSONResponse(
                status_code=err_data['status_code'],
                content={"data": {}, "msg": err_data['detail'], "code": err_data['status_code']}
            )
        else:
            # 传统的浏览器地址栏直接访问或表单提交出错 -> 渲染精美的错误 HTML 页面
            # 传入 request 和 错误信息 供模板渲染
            return templates.TemplateResponse(
                name="error/error.html",
                context={"request": request, "status_code": err_data['status_code'], "detail": err_data['detail']},
                status_code=err_data['status_code'],
                request=request,
            )

error.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>出错了 - {{ status_code }}</title>
</head>
<body>
    <div style="text-align: center; margin-top: 100px;">
        <h1>抱歉,系统响应异常 ({{ status_code }})</h1>
        <p style="color: red;">错误原因:{{ detail }}</p>
        <a href="/admin/dashboard">返回管理后台首页</a>
    </div>
</body>
</html>

 

 

二,测试效果 :

页面

image

json

image

posted @ 2026-07-23 18:48  刘宏缔的架构森林  阅读(1)  评论(0)    收藏  举报