mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-30 18:09:59 +03:00
Implement customizable exception handler
This commit is contained in:
parent
c8bed35621
commit
ae9ec60ce6
43
rest_framework/handlers.py
Normal file
43
rest_framework/handlers.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
"""Default handlers, configurable in settings"""
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import exceptions
|
||||
from rest_framework import status
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
|
||||
|
||||
def handle_exception(view_instance, exc):
|
||||
"""
|
||||
Default exception handler for APIView.
|
||||
|
||||
Handle any exception that occurs, by returning an appropriate response,
|
||||
or re-raising the error.
|
||||
"""
|
||||
if isinstance(exc, exceptions.Throttled):
|
||||
# Throttle wait header
|
||||
view_instance.headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait
|
||||
|
||||
if isinstance(exc, (exceptions.NotAuthenticated,
|
||||
exceptions.AuthenticationFailed)):
|
||||
# WWW-Authenticate header for 401 responses, else coerce to 403
|
||||
auth_header = view_instance.get_authenticate_header(
|
||||
view_instance.request)
|
||||
|
||||
if auth_header:
|
||||
view_instance.headers['WWW-Authenticate'] = auth_header
|
||||
else:
|
||||
exc.status_code = status.HTTP_403_FORBIDDEN
|
||||
|
||||
if isinstance(exc, exceptions.APIException):
|
||||
return Response(exc.data, status=exc.status_code,
|
||||
exception=True)
|
||||
elif isinstance(exc, Http404):
|
||||
return Response({'detail': 'Not found'},
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
exception=True)
|
||||
elif isinstance(exc, PermissionDenied):
|
||||
return Response({'detail': 'Permission denied'},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
exception=True)
|
||||
raise
|
|
@ -59,6 +59,9 @@ DEFAULTS = {
|
|||
'rest_framework.pagination.PaginationSerializer',
|
||||
'DEFAULT_FILTER_BACKENDS': (),
|
||||
|
||||
# Exception handling
|
||||
'DEFAULT_EXCEPTION_HANDLER': 'rest_framework.handlers.handle_exception',
|
||||
|
||||
# Throttling
|
||||
'DEFAULT_THROTTLE_RATES': {
|
||||
'user': None,
|
||||
|
@ -117,6 +120,7 @@ IMPORT_STRINGS = (
|
|||
'FILTER_BACKEND',
|
||||
'UNAUTHENTICATED_USER',
|
||||
'UNAUTHENTICATED_TOKEN',
|
||||
'DEFAULT_EXCEPTION_HANDLER',
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ class TestInstanceView(TestCase):
|
|||
self.assertIn('text', response.data)
|
||||
self.assertEqual(
|
||||
response.data['text'],
|
||||
[u'Ensure this value has at most 100 characters (it has 120).'])
|
||||
['Ensure this value has at most 100 characters (it has 120).'])
|
||||
|
||||
def test_put_to_deleted_instance(self):
|
||||
"""
|
||||
|
|
|
@ -5,8 +5,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import warnings
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.http import HttpResponse
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from rest_framework import status, exceptions
|
||||
|
@ -26,6 +25,7 @@ class APIView(View):
|
|||
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
|
||||
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
|
||||
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
|
||||
handle_exception = api_settings.DEFAULT_EXCEPTION_HANDLER
|
||||
|
||||
@classmethod
|
||||
def as_view(cls, **initkwargs):
|
||||
|
@ -265,38 +265,6 @@ class APIView(View):
|
|||
|
||||
return response
|
||||
|
||||
def handle_exception(self, exc):
|
||||
"""
|
||||
Handle any exception that occurs, by returning an appropriate response,
|
||||
or re-raising the error.
|
||||
"""
|
||||
if isinstance(exc, exceptions.Throttled):
|
||||
# Throttle wait header
|
||||
self.headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait
|
||||
|
||||
if isinstance(exc, (exceptions.NotAuthenticated,
|
||||
exceptions.AuthenticationFailed)):
|
||||
# WWW-Authenticate header for 401 responses, else coerce to 403
|
||||
auth_header = self.get_authenticate_header(self.request)
|
||||
|
||||
if auth_header:
|
||||
self.headers['WWW-Authenticate'] = auth_header
|
||||
else:
|
||||
exc.status_code = status.HTTP_403_FORBIDDEN
|
||||
|
||||
if isinstance(exc, exceptions.APIException):
|
||||
return Response(exc.data, status=exc.status_code,
|
||||
exception=True)
|
||||
elif isinstance(exc, Http404):
|
||||
return Response({'detail': 'Not found'},
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
exception=True)
|
||||
elif isinstance(exc, PermissionDenied):
|
||||
return Response({'detail': 'Permission denied'},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
exception=True)
|
||||
raise
|
||||
|
||||
# Note: session based authentication is explicitly CSRF validated,
|
||||
# all other authentication is CSRF exempt.
|
||||
@csrf_exempt
|
||||
|
|
Loading…
Reference in New Issue
Block a user