""" 错误处理中间件 功能: - 处理可预期的 HTTP 异常 - 处理未捕获的异常 - 返回统一错误结构 """ from __future__ import annotations from flask import g, jsonify, request from werkzeug.exceptions import HTTPException from outlook_web.errors import build_error_payload def handle_http_exception(error: HTTPException): """处理可预期的 HTTP 异常,返回统一错误结构(仅对 API/JSON 请求返回 JSON)""" status_code = error.code or 500 message_map = { 400: "请求参数错误", 401: "未授权", 403: "无权限", 404: "资源不存在", 405: "请求方法不被允许", 429: "请求过于频繁,请稍后再试", } message = message_map.get(status_code, "请求失败") trace_id_value = None try: trace_id_value = getattr(g, "trace_id", None) except Exception: trace_id_value = None error_payload = build_error_payload( code="HTTP_ERROR", message=message, err_type="HttpError", status=status_code, details=str(error), trace_id=trace_id_value, ) if request.path.startswith("/api/") or request.is_json: return jsonify({"success": False, "error": error_payload}), status_code return f"{message} (trace_id={error_payload.get('trace_id')})", status_code def handle_exception(error): """处理未捕获的异常""" trace_id_value = None try: trace_id_value = getattr(g, "trace_id", None) except Exception: trace_id_value = None try: from flask import current_app current_app.logger.exception("Unhandled exception trace_id=%s", trace_id_value or "unknown") except Exception: pass error_payload = build_error_payload( code="INTERNAL_ERROR", message="服务器内部错误", err_type="UnhandledException", status=500, details=str(error), trace_id=trace_id_value, ) if request.path.startswith("/api/") or request.is_json: return jsonify({"success": False, "error": error_payload}), 500 return f"服务器内部错误 (trace_id={error_payload.get('trace_id')})", 500