from apiflask import APIFlask, HTTPError from apiflask.exceptions import _ValidationError from iti.applications.common.utils import fail from iti.applications.common.exceptions.biz_exp import BizException from iti.applications.common.exceptions.permission import PermissionDeniedException def init_error_handler(app: APIFlask): """ 全局异常处理 """ @app.errorhandler(Exception) def handle_exception(error): """ 未处理的异常处理 """ try: # 安全地获取错误信息 error_msg = str(error) error_type = type(error).__name__ app.logger.error( f"服务器错误 [{error_type}]: {error_msg}", exc_info=True # 使用 exc_info 代替 stack_info,更安全 ) except Exception as log_error: # 如果日志记录失败,使用最基本的方式记录 try: app.logger.error(f"服务器错误(日志记录失败): {type(error).__name__}") except: pass # 完全失败则放弃日志记录 # 安全地返回错误信息 try: error_data = str(error) except: error_data = type(error).__name__ return fail(message="服务器错误", code=500, data=error_data) @app.errorhandler(400) def handle_400(error): """ 参数错误 """ try: app.logger.error(f"参数错误: {error}", exc_info=True) except: app.logger.error("参数错误(日志记录失败)") return fail( message=error.data.message if error.data and "message" in error.data else "参数错误", code=400, data=str(error), ) @app.errorhandler(BizException) def handle_biz_exception(error: BizException): """ 业务异常处理 """ try: app.logger.error(f"业务异常: {error}") except: app.logger.error("业务异常(日志记录失败)") return fail(error.message, code=error.code, data=error.data) @app.errorhandler(PermissionDeniedException) def handle_permission_denied_exception(error: PermissionDeniedException): """ 权限不足异常处理 """ try: app.logger.error(f"权限不足: {error}") except: app.logger.error("权限不足(日志记录失败)") return fail(message=error.message, code=error.code) @app.error_processor def handler_http_error(error: HTTPError): """ http异常处理 """ try: if isinstance(error, _ValidationError): app.logger.error(f"参数验证错误: {error.detail}") error.message = "参数验证错误" else: app.logger.error( f"HTTP异常: {error.message} {error.status_code} {error.detail} {error.headers} {error.extra_data}" ) except: app.logger.error("HTTP异常(日志记录失败)") return ( fail(message=error.message, code=error.status_code, data=error.detail), 200, error.headers, )