Files
Django/utils/exception_handler.py

81 lines
3.6 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.
# /opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django/utils/exception_handler.py
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
import logging
import os
logger = logging.getLogger('django')
def custom_exception_handler(exc, context):
"""
生产环境安全异常处理器 - 不泄露任何敏感信息
基于你之前项目的代码,做了小优化
"""
# 先调用默认异常处理器
response = exception_handler(exc, context)
if response is not None:
# 🔥 记录原始错误信息到日志(便于排查)
request = context['request']
user_info = f"用户: {request.user.id if request.user.is_authenticated else '未登录'}"
logger.error(
f"API异常 - 路径: {request.path}, "
f"方法: {request.method}, {user_info}, "
f"状态码: {response.status_code}, 错误: {str(exc)}"
)
# 🔥 生产环境返回标准化错误,不暴露任何细节
error_messages = {
status.HTTP_400_BAD_REQUEST: {'code': 400, 'message': '请求参数错误'},
status.HTTP_401_UNAUTHORIZED: {'code': 401, 'message': '请先登录'},
status.HTTP_403_FORBIDDEN: {'code': 403, 'message': '权限不足'},
status.HTTP_404_NOT_FOUND: {'code': 404, 'message': '资源不存在'},
status.HTTP_405_METHOD_NOT_ALLOWED: {'code': 405, 'message': '请求方法不允许'},
status.HTTP_408_REQUEST_TIMEOUT: {'code': 408, 'message': '请求超时'},
status.HTTP_429_TOO_MANY_REQUESTS: {'code': 429, 'message': '请求过于频繁'},
status.HTTP_500_INTERNAL_SERVER_ERROR: {'code': 500, 'message': '服务器内部错误'},
status.HTTP_502_BAD_GATEWAY: {'code': 502, 'message': '网关错误'},
status.HTTP_503_SERVICE_UNAVAILABLE: {'code': 503, 'message': '服务暂不可用'},
status.HTTP_504_GATEWAY_TIMEOUT: {'code': 504, 'message': '网关超时'},
}
# 🔥 如果是调试模式,返回详细错误(便于开发)
from django.conf import settings
if settings.DEBUG:
return response
# 🔥 生产环境返回标准错误
standard_response = error_messages.get(
response.status_code,
{'code': response.status_code, 'message': '请求错误'}
)
return Response(standard_response, status=response.status_code)
# 对于非DRF异常response为None生产环境返回通用错误信息
if response is None:
from django.conf import settings
request = context.get('request')
user_info = '未知'
if request:
user_info = f"用户: {request.user.id if request.user.is_authenticated else '未登录'}"
logger.error(
f"未处理异常 - 路径: {request.path if request else '未知'}, "
f"方法: {request.method if request else '未知'}, {user_info}, "
f"错误类型: {type(exc).__name__}, 错误: {str(exc)}"
)
if not settings.DEBUG:
import traceback
print(traceback.format_exc())
return Response(
{'code': 500, 'message': '服务器内部错误,请稍后重试'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
return Response(
{'code': 500, 'message': str(exc)},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
return response