Files
outlookEmailPlus/outlook_web/middleware/error_handler.py
T
胡绍康andClaude Opus 4.6 c0562ef721 refactor: 迁移中间件到 middleware 模块
创建 outlook_web/middleware/ 目录,从 legacy.py 迁移:

新增文件:
- middleware/__init__.py - 模块导出
- middleware/trace.py - trace_id 中间件
  - ensure_trace_id(): 为每个请求生成/透传 trace_id
  - attach_trace_id_and_normalize_errors(): 统一写入 X-Trace-Id,标准化错误格式
- middleware/error_handler.py - 错误处理中间件
  - handle_http_exception(): 处理 HTTP 异常
  - handle_exception(): 处理未捕获异常

更新文件:
- app.py: 从 middleware 模块导入,替代 legacy 引用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:47:45 +08:00

79 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
错误处理中间件
功能:
- 处理可预期的 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