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)
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
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
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)
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)
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
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
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
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)
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)
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
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
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
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
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)
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
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
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)
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
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
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
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)
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
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
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
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
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)
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
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
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
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
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