Esempio n. 1
0
def exception_handler(exc, context):
    """Handle Django ValidationError as an accepted exception
    Must be set in settings:
    >>> REST_FRAMEWORK = {
    ...     # ...
    ...     'EXCEPTION_HANDLER': 'mtp.apps.common.drf.exception_handler',
    ...     # ...
    ... }
    For the parameters, see ``exception_handler``
    """

    if isinstance(exc, DjangoValidationError):
        if hasattr(exc, "message_dict"):
            new_dict = {}
            for key, value in exc.message_dict.items():
                if type(value) in (list, tuple, set,
                                   frozenset) and len(value) == 1:
                    new_dict[key] = value[0]
                else:
                    new_dict[key] = value
            detail = new_dict
        elif hasattr(exc, "message"):
            detail = {'detail': exc.message}
        elif hasattr(exc, "messages"):
            detail = exc.messages
        else:
            return drf_exception_handler(exc, context)

        exc = DRFValidationError(detail=detail)

    return drf_exception_handler(exc, context)
Esempio n. 2
0
def exception_handler(exception, context):
    if isinstance(exception, DjangoValidationError):
        message = getattr(exception, 'message', None)
        messages = getattr(exception, 'messages', None)
        detail = {'non_field_errors': messages or [message]}
        exception = DRFValidationError(detail=detail)

    response = drf_exception_handler(exception, context)
    if response is None:
        exception = APIException(exception)
        return drf_exception_handler(exception, context)

    return response
Esempio n. 3
0
def exception_handler(exc, context):
    # Import this here to avoid potential edge-case circular imports, which
    # crashes with:
    # "ImportError: Could not import 'rest_framework_json_api.parsers.JSONParser' for API setting
    # 'DEFAULT_PARSER_CLASSES'. ImportError: cannot import name 'exceptions'.'"
    #
    # Also see: https://github.com/django-json-api/django-rest-framework-json-api/issues/158
    from rest_framework.views import exception_handler as drf_exception_handler

    # Render exception with DRF
    response = drf_exception_handler(exc, context)
    if not response:
        return response

    # Use regular DRF format if not rendered by DRF JSON API and not uniform
    is_json_api_view = rendered_with_json_api(context['view'])
    is_uniform = json_api_settings.UNIFORM_EXCEPTIONS
    if not is_json_api_view and not is_uniform:
        return response

    # Convert to DRF JSON API error format
    response = utils.format_drf_errors(response, context, exc)

    # Add top-level 'errors' object when not rendered by DRF JSON API
    if not is_json_api_view:
        response.data = utils.format_errors(response.data)

    return response
Esempio n. 4
0
def custom_exception_handler(exc, context):
    if isinstance(exc, PermissionDenied):
        exc = PermissionDenied(
            detail={'message': 'Ошибка доступа. У вас нет прав.'})

    if isinstance(exc, NotAuthenticated):
        exc = NotAuthenticated(
            detail={'message': 'Ошибка доступа. Вы не авторизованы'})

    if isinstance(exc, CustomValidation):
        field = list(exc.detail.keys())[0]
        exc = DRFValidationError(
            detail={'message': field + ' ' + exc.detail[field]})

    if isinstance(exc, DjangoValidationError):
        if hasattr(exc, 'message_dict'):
            # TODO: handle many fields
            field = list(exc.detail.keys())[0]

            exc = DRFValidationError(
                detail={'message': field + ' ' + exc.detail[field]})
        else:
            exc = DRFValidationError(detail={'message': exc.message})

    if isinstance(exc, DjangoIntegrityError):
        exc = DRFValidationError(detail={'message': str(exc)})

    return drf_exception_handler(exc, context)
Esempio n. 5
0
def exception_handler(exception, context):
    """Handle Django ValidationError as an accepted exception
    Must be set in settings:
    >>> REST_FRAMEWORK = {
    ...     # ...
    ...     'EXCEPTION_HANDLER': 'Authentication.exception_handler.exception_handler',
    ...     # ...
    ... }
    For the parameters, see ``exception_handler``
    """

    if isinstance(exception, DjangoValidationError):
        if isinstance(exception, DjangoValidationError):
            if hasattr(exception, 'message_dict'):
                detail = exception.message_dict
            elif hasattr(exception, 'message'):
                detail = exception.message
            elif hasattr(exception, 'messages'):
                detail = exception.messages
            else:
                logging.error("BAD VALIDATION MESSAGE: %s" % exception)

            exception = DRFValidationError(detail={"detail": detail})

    return drf_exception_handler(exception, context)
Esempio n. 6
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if response is not None:
        data = getattr(response, 'data', {})
        request = context.get('request', object)

        response.data = OrderedDict([
            ('type', exc.__class__.__name__),
            ('title', response.status_text),
            ('status', response.status_code),
            ('detail', data.get('detail', '')),
            ('instance', getattr(request, 'path', '')),
        ])

        if isinstance(exc, exceptions.ValidationError):
            response.data['invalid_params'] = [
                OrderedDict([
                    ('type', exc.__class__.__name__),
                    ('name', field_name),
                    ('reason', '; '.join(message))
                ])
                for field_name, message in exc.detail.items()
            ]

    return response
Esempio n. 7
0
def exception_handler(exc, context):
    """
    自定义异常处理
    :param exc: 异常
    :param context: 异常上下文
    :return: Response响应对象
    """
    response = drf_exception_handler(exc, context)

    if response is None:
        errmsg = None
        if settings.DEBUG:
            errmsg = str(exc)
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 数据库异常
            logger.error(traceback.format_exc())
            response = CstResponse(RET.DBERR, errmsg)
        elif isinstance(exc, CstException):
            response = CstResponse(exc.code, exc.message)
        else:
            logger.error(traceback.format_exc())
            response = CstResponse(RET.SERVERERR, errmsg)
    if response and response.status_code == 400:
        logger.error(str(exc.detail))
        response = CstResponse(RET.DATAERR, exc.detail)

    if response and response.status_code != 200:
        logger.error(str(exc.detail))
        response = CstResponse(RET.DBERR, exc.detail)

    return response
Esempio n. 8
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    if response is None:
        if isinstance(exc, DatabaseError):
            return Response({'detail': '数据库错误'},
                            status=status.HTTP_507_INSUFFICIENT_STORAGE)
    return response
Esempio n. 9
0
def exception_handler(exc, context):
    """Handle Django ValidationError as an accepted exception

    Must be set in settings:

    >>> REST_FRAMEWORK = {
    ...     # ...
    ...     'EXCEPTION_HANDLER': 'mtp.apps.common.drf.exception_handler',
    ...     # ...
    ... }

    For the parameters, see ``exception_handler``

    """

    if isinstance(exc, DjangoValidationError):
        try:
            exc = DRFValidationError(detail=exc.message_dict)
        except AttributeError:
            exc = DRFValidationError(detail={"validation_error": exc.message})

    if isinstance(exc, ProtectedError):
        exc = DRFValidationError(detail={"protection_error": exc.args[0]})

    return drf_exception_handler(exc, context)
def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    if isinstance(exc, DjangoValidationError):
        exc = DRFValidationError(detail=exc.message_dict)

    return drf_exception_handler(exc, context)
Esempio n. 11
0
def exception_handler(exception, context):
    # Transform model validation errors into an equivalent DRF ValidationError.
    if isinstance(exception, DjangoValidationError):
        exception = DRFValidationError(detail=get_error_detail(exception))

    # Call REST Framework's default exception handler with the transformed exception.
    return drf_exception_handler(exception, context)
Esempio n. 12
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    if response is None:
        if isinstance(exc, DatabaseError):
            response = Response({'detail': '数据库错误'},
                                status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return response
Esempio n. 13
0
def exception_handler(exc, context):
    """
    Custom exception handler for REST responses

    Currently used to properly turn django ObjectDoesNotExist
    errors into 404 api responses.
    """

    # call default handler first

    response = Response({})
    if isinstance(exc, ObjectDoesNotExist):
        response.data = {"errors": {"non_field_errors": f"{exc}"}}
        response.status_code = 404
    elif isinstance(exc, IntegrityError):
        response.data = {"non_field_errors": f"{exc}"}
        response.status_code = 400
    elif isinstance(exc, Http404):
        if getattr(context.get("request"), "destroyed", False):
            return Response({}, status=status.HTTP_204_NO_CONTENT)
        else:
            response.status_code = 404
    else:
        response = drf_exception_handler(exc, context)

    return response
Esempio n. 14
0
def exception_handler(exc, context):
    # Convert Django exceptions (from DRF).
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.PermissionDenied()
    elif not isinstance(exc, exceptions.APIException):
        # Fallback handler to convert remaining exceptions to API exception.
        logger.exception(exc)
        exc = exceptions.APIException(exc)

    request = context['request']
    response = drf_exception_handler(exc, context)
    data = response.data

    problem_title = getattr(exc, 'title', exc.default_detail)
    problem_status = response.status_code
    problem_code = getattr(exc, 'code', exc.default_code)
    problem_type = reverse('drf_problems:error-documentation',
                           kwargs={'code': problem_code}, request=request)
    if isinstance(data, dict):
        data['title'] = problem_title
        data['status'] = problem_status
        data['type'] = problem_type
    else:
        data = dict(errors=response.data, title=problem_title,
                    status=problem_status, type=problem_type)
    try:
        if request.accepted_renderer.format == 'json':
            response.content_type = 'application/problem+json'
    except AttributeError:
        pass
    response.data = data

    return response
Esempio n. 15
0
def exception_handler(exc, context):
    """
    自定义异常处理
    :param exc: 异常
    :param context: 抛出异常的上下文
    :return: Response响应对象
    """
    # 调用drf框架原生的异常处理方法(系统处理异常)
    response = drf_exception_handler(exc, context)

    if response is None:
        view = context['view']
        # if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
        if isinstance(exc, DatabaseError):
            # 数据库异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': 'Mysql数据库错误'},
                                status=status.HTTP_507_INSUFFICIENT_STORAGE)
        elif isinstance(exc, RedisError):
            # 数据库异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': 'Redis数据库错误'},
                                status=status.HTTP_507_INSUFFICIENT_STORAGE)

    return response
Esempio n. 16
0
def exception_handler(exc, context):
    """Handle Django ValidationError as an accepted exception."""

    if isinstance(exc, DjangoValidationError):
        exc = DRFValidationError(detail=exc.messages)

    return drf_exception_handler(exc, context)
Esempio n. 17
0
def exception_handler(exc, context):
    """
    Return special responses on exceptions not supported by drf.
    """
    response = drf_exception_handler(exc, context)

    # Check for IntegrityError, use a custom status code for this.
    if not response and isinstance(exc, IntegrityError):
        set_rollback()
        response = Response(
            {'detail': 'Some values are supposed to be unique but are not.'},
            status=status.HTTP_409_CONFLICT)

    if response:
        detail = None
        if isinstance(response.data, dict):
            detail = response.data.get('detail')

        log.warn('request_error',
                 status_code=response.status_code,
                 detail=detail,
                 exc=exc)
    else:
        log.error('unhandled_request_exception', exc=exc)

    return response
Esempio n. 18
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if response is not None:
        data = getattr(response, "data", {})
        request = context.get("request", object)

        response.data = OrderedDict([
            ("type", exc.__class__.__name__),
            ("title", response.status_text),
            ("status", response.status_code),
            ("detail", data.get("detail", "")),
            ("instance", getattr(request, "path", "")),
        ])

        if isinstance(exc, exceptions.ValidationError):
            response.data["invalid_params"] = [
                OrderedDict([
                    ("type", exc.__class__.__name__),
                    ("name", field_name),
                    ("reason", "; ".join(message)),
                ]) for field_name, message in exc.detail.items()
            ]

    return response
Esempio n. 19
0
def rest_exception_handler(e, context):
    response = drf_exception_handler(e, context)
    request = context["request"]

    if isinstance(e, TaskwarriorError):
        # Note -- this error message will be printed to the USER's
        # error log regardless of whether or not the error that occurred
        # was a problem with their task list, or that of a Kanban board.
        store = TaskStore.get_for_user(request.user)
        message = f"({e.code}) {e.stderr}"
        store.log_silent_error(f"Taskwarrior Error: {message}")
        return Response(
            {"error_message": message},
            status=400,
        )
    elif isinstance(e, LockTimeout):
        message = "Your task list is currently in use; please try again later."
        store = TaskStore.get_for_user(request.user)
        store.log_error(message)
        return Response(
            {
                "error_message":
                ("Your task list is currently in use; please try "
                 "again later.")
            },
            status=409,
        )
    elif isinstance(e, PermissionDenied):
        return Response(status=401)
    elif isinstance(e, ObjectDoesNotExist):
        return Response(status=404)
    else:
        return response
def custom_exception_handler(exc, context):
    """
        DRF 의 Global Error handler 를 customizing 을 하는 것이며,
        기존의 처리는 그대로 맞기며, 그외의 경우는
        내가 만든 Global Error 을 바탕으로 만들었다.

        주로, Return 할 떄, 코드의 가독성을 위해서 만든 경우가 대부분이다.
    """
    # print("exc", exc)
    # print("type(exc)", type(exc))

    if isinstance(exc, (APIException, Http404, PermissionDenied)):
        response = drf_exception_handler(exc, context)
        # Now add the HTTP status code to the response.
        if response is not None:
            response.data['status_code'] = response.status_code
        return response

    if isinstance(exc, GlobalErrorMessage):
        return Response({'response': 'error', 'message': str(exc)})

    if isinstance(exc, GlobalErrorMessage400):
        return Response({
            'response': 'error',
            'message': str(exc)
        },
                        status=status.HTTP_400_BAD_REQUEST)

    if isinstance(exc, GlobalErrorMessage401):
        return Response({
            'response': 'error',
            'message': str(exc)
        },
                        status=status.HTTP_401_UNAUTHORIZED)
Esempio n. 21
0
def exception_handler(exc, context):
    """Return the exceptions as 'application/problem+json'.

    See: https://tools.ietf.org/html/rfc7807
    """
    request = context.get("request")
    response = drf_exception_handler(exc, context)
    if response is None:
        return None

    if isinstance(exc, ValidationError):
        # response.data are the fields
        response.data = {
            "type": f"urn:apiexception:{exc.default_code}",
            "title": str(exc.default_detail),
            "status": response.status_code,
            "instance": request.build_absolute_uri() if request else None,
            "invalid-params": get_invalid_params(exc, exc.detail),
            # Also include the whole tree of recursive errors that DRF generates
            "x-validation-errors": response.data,
        }

        response.content_type = "application/problem+json"
    elif isinstance(exc, RemoteAPIException):
        # Raw problem json response forwarded (for RemoteViewSet)
        # Normalize the problem+json fields to be identical to how
        # our own API's would return these.
        normalized_fields = {
            "type": f"urn:apiexception:{exc.code}",
            "code": exc.code,
            "title": exc.default_detail,
            "status": int(exc.status_code),
            "instance": request.build_absolute_uri() if request else None,
        }
        # This merge stategy puts the normal fields first:
        response.data = {**normalized_fields, **response.data}
        response.data.update(normalized_fields)
        response.status_code = int(exc.status_code)
        response.content_type = "application/problem+json"
    elif isinstance(response.data.get("detail"), ErrorDetail):
        # DRF parsed the exception as API
        detail = response.data["detail"]
        response.data = {
            "type":
            f"urn:apiexception:{detail.code}",
            "title":
            exc.default_detail if hasattr(exc, "default_detail") else str(exc),
            "detail":
            str(detail),
            "status":
            response.status_code,
        }

        # Returning a response with explicit content_type breaks the browsable API,
        # as that only returns text/html as it's default type.
        response.content_type = "application/problem+json"
    else:
        response.content_type = "application/json"  # Avoid being hal-json

    return response
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if not response:
        return response

    errors = []
    # handle generic errors. ValidationError('test') in a view for example
    if isinstance(response.data, list):
        for message in response.data:
            errors.append({
                'detail': message,
                'source': {
                    'pointer': '/data',
                },
                'status': encoding.force_text(response.status_code),
            })
    # handle all errors thrown from serializers
    else:
        for field, error in response.data.items():
            field = format_value(field)
            pointer = '/data/attributes/{}'.format(field)
            # see if they passed a dictionary to ValidationError manually
            if isinstance(error, dict):
                errors.append(error)
            elif isinstance(error, six.string_types):
                classes = inspect.getmembers(exceptions, inspect.isclass)
                # DRF sets the `field` to 'detail' for its own exceptions
                if isinstance(exc, tuple(x[1] for x in classes)):
                    pointer = '/data'
                errors.append({
                    'detail': error,
                    'source': {
                        'pointer': pointer,
                    },
                    'status': encoding.force_text(response.status_code),
                })
            elif isinstance(error, list):
                for message in error:
                    errors.append({
                        'detail': message,
                        'source': {
                            'pointer': pointer,
                        },
                        'status': encoding.force_text(response.status_code),
                    })
            else:
                errors.append({
                    'detail': error,
                    'source': {
                        'pointer': pointer,
                    },
                    'status': encoding.force_text(response.status_code),
                })


    context['view'].resource_name = 'errors'
    response.data = errors
    return response
Esempio n. 23
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    print(exc)
    print(context)
    if response is None:
        return Response({'detail': '服务器错误'},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return response
Esempio n. 24
0
def exception_handler(exc, context):
    """调用默认"""
    response = drf_exception_handler(exc, context)
    if response is None:
        print("exc:{exc}---view:{view}---args:{args}---kwargs:{kwargs}".format(
            exc=exc, **context))
        response = Response({"detail": "服务器错误"})
    return response
Esempio n. 25
0
def exception_handler(exc, context):
    if isinstance(exc, DjangoValidationError):
        if hasattr(exc, 'message_dict'):
            exc = DRFValidationError(detail=exc.message_dict)
        else:
            exc = DRFValidationError(detail=exc.message)

    return drf_exception_handler(exc, context)
Esempio n. 26
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if isinstance(exc, Ratelimited):
        response.data['detail'] = 'Too many requests, try again later'
        response.status_code = 429

    return response
Esempio n. 27
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    if response is None:
        print(f"{context['view']} - {context['request'].method} - {exc}")
        return Response({'detail': 'server error'},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        exception=True)
    return response
Esempio n. 28
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    error = "%s %s %s" % (context['view'], context['request'].method, exc)
    if response is None:
        return Response({"error": "刷新一下马上就好了!"},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        exception=None)
    return response
Esempio n. 29
0
def exception_handler(exc, context):
    """自定义异常处理函数"""
    response = drf_exception_handler(exc, context)
    if response is None:
        if isinstance(exc, DataError):
            response = Response({'errmsg': '数据库出错'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return response
Esempio n. 30
0
def exception_handler(exc, context):
    """
    desecapi specific exception handling. If no special treatment is applied,
    we default to restframework's exception handling. See also
    https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling
    """
    def _log():
        logger = logging.getLogger('django.request')
        logger.error('{} Supplementary Information'.format(exc.__class__),
                     exc_info=exc,
                     stack_info=False)

    def _500():
        _log()

        # Let clients know that there is a problem
        response = Response({'detail': 'Internal Server Error. We\'re on it!'},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        return response

    def _503():
        _log()

        # Let clients know that there is a temporary problem
        response = Response({'detail': 'Please try again later.'},
                            status=status.HTTP_503_SERVICE_UNAVAILABLE)
        return response

    # Catch DB exception and log an extra error for additional context
    if (isinstance(exc, OperationalError)
            and isinstance(exc.args, (list, dict, tuple)) and exc.args
            and exc.args[0] in (
                2002,  # Connection refused (Socket)
                2003,  # Connection refused (TCP)
                2005,  # Unresolved host name
                2007,  # Server protocol mismatch
                2009,  # Wrong host info
                2026,  # SSL connection error
            )):
        metrics.get('desecapi_database_unavailable').inc()
        return _503()

    # OSError happens on system-related errors, like full disk or getaddrinfo() failure.
    if isinstance(exc, OSError):
        # TODO add metrics
        return _500()

    # The PSL encountered an unsupported rule
    if isinstance(exc, UnsupportedRule):
        # TODO add metrics
        return _500()

    # nslord/nsmaster returned an error
    if isinstance(exc, PDNSException):
        # TODO add metrics
        return _500()

    return drf_exception_handler(exc, context)
Esempio n. 31
0
def exception_handler(exc, context):
    error = "%s %s %s" % (context['view'], context["request"].method, exc)
    response = drf_exception_handler(exc, context)
    if response is None:
        logger.error(error)
        return Response({
            "error_msg": "程序内部错误,请稍等一会"
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=None)
    return response
Esempio n. 32
0
def exception_handler(exception, context):
    """
    Overwriting Django Rest Frameworks exception handler to provide more
    meaniful exception messages for 404 errors.
    """
    exception = set_exception(exception)

    response = drf_exception_handler(exception, context)

    if response:
        response.data = eval_json(response.data)

        return response
Esempio n. 33
0
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    if getattr(context.get('view'), 'bypass_jsonapi_exception_handler', False):
        context['view'].is_errored = True
        return response
    if response is None:
        # Unhandled exceptions will raise a 500 error.
        return

    errors = []
    # Handle views errors
    if isinstance(response.data, list):
        for message in response.data:
            errors.append({
                "detail": message,
                "source": {
                    "pointer": "/data",
                },
                "status": six.text_type(response.status_code),
            })
    # Handle all other errors
    elif isinstance(response.data, dict):
        for field, error in response.data.items():
            # Field errors
            if isinstance(error, list):
                field = dasherize(field)
                pointer = "/data/attributes/{}".format(field)
                for message in error:
                    errors.append({
                        "detail": message,
                        "source": {
                            "pointer": pointer,
                        },
                        "status": six.text_type(response.status_code),
                    })
            # Other errors (e.g. Http404, PermissionDenied, throttling errors)
            elif field == "detail" and isinstance(error, six.string_types):
                errors.append({
                    "detail": error,
                    "source": {
                        "pointer": "/data",
                    },
                    "status": six.text_type(response.status_code),
                })

    response.data = OrderedDict([
        ("jsonapi", OrderedDict([("version", "1.0")])),
        ("errors", errors)
    ])
    context['view'].is_errored = True
    return response
Esempio n. 34
0
    def handle_exception(cls, exc, *args, **kwargs):
        """
        Typically the exception will have enough data to represent itself (i.e. status_code, message).
        Otherwise we'll have to map the exception to a local exception in EXCEPTION_MAPPING.

        """
        if isinstance(exc, BaseAPIException):
            logger.warning('Encountered APIError when processing api request.', exc_info=True)
            return APIErrorResponse(
                status=exc.status_code,
                error_list=exc.error_list
            )
        elif isinstance(exc, ParseError):
            return APIErrorResponse(
                error_list=[{"code": 0, "title": ERROR_CODES[0], "detail": exc.detail}],
                status=status.HTTP_400_BAD_REQUEST,
            )
        else:
            # exception wasnt a custom `APIError` fallback to DRF exception handling
            response = drf_exception_handler(exc, *args, **kwargs)

            if response:
                logger.warning('Encountered DRF exception when processing api request.', exc_info=True)
                # need to format DRF error response to our style of error response
                # as DRF may have added headers and other details to the response

                return APIErrorResponse(
                    error_list=[OrderedDict(
                        code=10,
                        title=ERROR_CODES[10],
                        detail=response.data.pop('detail'),
                    )],
                    status=status.HTTP_400_BAD_REQUEST,
                )
            else:
                logger.error('Encountered an unhandleded api exception when processing api request.', exc_info=True)
                if not settings.DEBUG:
                    return APIErrorResponse(
                        error_list=[OrderedDict(
                            code=20,
                            title=ERROR_CODES[20],
                            detail=(
                                'An unexpted error has occured while processing your request, our engineers have been altered. '
                                'You can also contact our support if this error is blocking you.'),
                        )],
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    )
            # fallback to django exception handling
            logger.warning('Encountered an unhandled exception when processing api request.')
            return None
Esempio n. 35
0
def rest_exception_handler(e, context):
    response = drf_exception_handler(e, context)
    request = context['request']

    if isinstance(e, TaskwarriorError):
        # Note -- this error message will be printed to the USER's
        # error log regardless of whether or not the error that occurred
        # was a problem with their task list, or that of a Kanban board.
        store = TaskStore.get_for_user(request.user)
        message = '(%s) %s' % (
            e.code,
            e.stderr,
        )
        store.log_silent_error(
            'Taskwarrior Error: %s' % message
        )
        return Response(
            {
                'error_message': message
            },
            status=400,
        )
    elif isinstance(e, LockTimeout):
        message = (
            'Your task list is currently in use; please try again later.'
        )
        store = TaskStore.get_for_user(request.user)
        store.log_error(message)
        return Response(
            {
                'error_message': (
                    'Your task list is currently in use; please try '
                    'again later.'
                )
            },
            status=409
        )
    elif isinstance(e, PermissionDenied):
        return Response(status=401)
    elif isinstance(e, ObjectDoesNotExist):
        return Response(status=404)
    else:
        return response
def exception_handler(exc, context):
    # Import this here to avoid potential edge-case circular imports, which
    # crashes with:
    # "ImportError: Could not import 'rest_framework_json_api.parsers.JSONParser' for API setting
    # 'DEFAULT_PARSER_CLASSES'. ImportError: cannot import name 'exceptions'.'"
    #
    # Also see: https://github.com/django-json-api/django-rest-framework-json-api/issues/158
    from rest_framework.views import exception_handler as drf_exception_handler
    response = drf_exception_handler(exc, context)

    if not response:
        return response

    errors = []
    # handle generic errors. ValidationError('test') in a view for example
    if isinstance(response.data, list):
        for message in response.data:
            errors.append({
                'detail': message,
                'source': {
                    'pointer': '/data',
                },
                'status': encoding.force_text(response.status_code),
            })
    # handle all errors thrown from serializers
    else:
        for field, error in response.data.items():
            field = format_value(field)
            pointer = '/data/attributes/{}'.format(field)
            # see if they passed a dictionary to ValidationError manually
            if isinstance(error, dict):
                errors.append(error)
            elif isinstance(error, six.string_types):
                classes = inspect.getmembers(exceptions, inspect.isclass)
                # DRF sets the `field` to 'detail' for its own exceptions
                if isinstance(exc, tuple(x[1] for x in classes)):
                    pointer = '/data'
                errors.append({
                    'detail': error,
                    'source': {
                        'pointer': pointer,
                    },
                    'status': encoding.force_text(response.status_code),
                })
            elif isinstance(error, list):
                for message in error:
                    errors.append({
                        'detail': message,
                        'source': {
                            'pointer': pointer,
                        },
                        'status': encoding.force_text(response.status_code),
                    })
            else:
                errors.append({
                    'detail': error,
                    'source': {
                        'pointer': pointer,
                    },
                    'status': encoding.force_text(response.status_code),
                })


    context['view'].resource_name = 'errors'
    response.data = errors
    return response