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>
二,测试效果 :
页面

json

浙公网安备 33010602011771号