# DRF Rack # Библиотека классов расширений для Django REST Framework # # Автор: Николай В. Анохин # Все права защищены. Лицензия: MIT """ Описание функции custom_exception_handler """ from rest_framework import status from rest_framework.exceptions import MethodNotAllowed from rest_framework.exceptions import NotAuthenticated from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import ValidationError from rest_framework.request import Request from rest_framework.response import Response from net.xeaf.rack.core import CoreException from net.xeaf.rack.models.responses import ErrorResponse from net.xeaf.rack.utils.exceptions import ForbiddenException from net.xeaf.rack.utils.exceptions import NotFoundException from net.xeaf.rack.utils.exceptions import UnauthorizedException def custom_exception_handler(exc: CoreException | Exception, context: dict) -> Response: """ Универсальный обработчик исключений :param exc: Исключение :param context: Контекст :return: Ответ """ # Получаем информацию о запросе request = context.get("request") assert isinstance(request, Request) # Это наше исключение if isinstance(exc, CoreException): return ErrorResponse(status_code=exc.status_code, detail=exc.detail, meta=exc.meta) # Проверка на стандартное исключение валидации if isinstance(exc, ValidationError): return _process_validation_exception(exc) # Проверка на стандартное исключение авторизации if isinstance(exc, NotAuthenticated): return ErrorResponse(status_code=status.HTTP_401_UNAUTHORIZED, detail=UnauthorizedException.Msg.DEFAULT_MESSAGE) # Проверка на стандартное исключение прав доступа if isinstance(exc, PermissionDenied): return ErrorResponse(status_code=status.HTTP_403_FORBIDDEN, detail=ForbiddenException.Msg.DEFAULT_MESSAGE) # Проверка на стандартное исключение отсутствия реализации if isinstance(exc, MethodNotAllowed): return ErrorResponse(status_code=status.HTTP_404_NOT_FOUND, detail=NotFoundException.Msg.DEFAULT_MESSAGE) # Если ничего другое не прошло return ErrorResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) def _process_validation_exception(exc: ValidationError) -> ErrorResponse: """ Обрабатывает частный случай стандартного исключения валидации :param exc: Исключение :return: Ответ """ if isinstance(exc.detail, list): if len(exc.detail) == 1: detail = str(exc.detail[0]) else: detail = exc.detail elif isinstance(exc.detail, dict): detail = {} for field, error_info in exc.detail.items(): if isinstance(error_info, list): error = error_info[0] detail[field] = str(error) else: detail = str(exc.detail) return ErrorResponse(status_code=status.HTTP_400_BAD_REQUEST, detail=detail)