From 1befab795a9253b87b6713f618129241e4846e07 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 3 Apr 2018 09:16:36 +0200 Subject: [PATCH] Added generic 500 and 400 JSON error handlers. (#5904) * Added generic 500 and 400 JSON error handlers. * Docs for generic error views. --- docs/api-guide/exceptions.md | 28 ++++++++++++++++++++++++++++ rest_framework/exceptions.py | 21 +++++++++++++++++++++ tests/test_exceptions.py | 21 +++++++++++++++++++-- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index ba3d5af9b..d0fc4beaa 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -230,5 +230,33 @@ The generic views use the `raise_exception=True` flag, which means that you can By default this exception results in a response with the HTTP status code "400 Bad Request". + +--- + +# Generic Error Views + +Django REST Framework provides two error views suitable for providing generic JSON `500` Server Error and +`400` Bad Request responses. (Django's default error views provide HTML responses, which may not be appropriate for an +API-only application.) + +Use these as per [Django's Customizing error views documentation][django-custom-error-views]. + +## `rest_framework.exceptions.server_error` + +Returns a response with status code `500` and `application/json` content type. + +Set as `handler500`: + + handler500 = 'rest_framework.exceptions.server_error' + +## `rest_framework.exceptions.server_error` + +Returns a response with status code `400` and `application/json` content type. + +Set as `handler400`: + + handler400 = 'rest_framework.exceptions.bad_request' + [cite]: https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/ [authentication]: authentication.md +[django-custom-error-views]: https://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index 492872ae5..3c64386da 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -8,6 +8,7 @@ from __future__ import unicode_literals import math +from django.http import JsonResponse from django.utils import six from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ @@ -235,3 +236,23 @@ class Throttled(APIException): wait)))) self.wait = wait super(Throttled, self).__init__(detail, code) + + +def server_error(request, *args, **kwargs): + """ + Generic 500 error handler. + """ + data = { + 'error': 'Server Error (500)' + } + return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +def bad_request(request, exception, *args, **kwargs): + """ + Generic 400 error handler. + """ + data = { + 'error': 'Bad Request (400)' + } + return JsonResponse(data, status=status.HTTP_400_BAD_REQUEST) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 006191a49..0c5ff7aae 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,11 +1,13 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.test import TestCase +from django.test import RequestFactory, TestCase from django.utils import six, translation from django.utils.translation import ugettext_lazy as _ from rest_framework.exceptions import ( - APIException, ErrorDetail, Throttled, _get_error_details + APIException, ErrorDetail, Throttled, _get_error_details, bad_request, + server_error ) @@ -87,3 +89,18 @@ class TranslationTests(TestCase): # this test largely acts as a sanity test to ensure the translation files are present. self.assertEqual(_('A server error occurred.'), 'Une erreur du serveur est survenue.') self.assertEqual(six.text_type(APIException()), 'Une erreur du serveur est survenue.') + + +def test_server_error(): + request = RequestFactory().get('/') + response = server_error(request) + assert response.status_code == 500 + assert response["content-type"] == 'application/json' + + +def test_bad_request(): + request = RequestFactory().get('/') + exception = Exception('Something went wrong — Not used') + response = bad_request(request, exception) + assert response.status_code == 400 + assert response["content-type"] == 'application/json'