From 51760a6ed8853b66d11fc482fda2bfc727068822 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 27 Mar 2018 12:02:32 +0200 Subject: [PATCH 1/4] Added generic 500 and 400 JSON error handlers. --- rest_framework/exceptions.py | 21 +++++++++++++++++++++ tests/test_exceptions.py | 20 ++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index 492872ae5b..3c64386da6 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -8,6 +8,7 @@ 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 @@ def __init__(self, wait=None, detail=None, code=None): 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 006191a491..c0ea957941 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,11 +1,12 @@ 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 +88,18 @@ def test_message(self): # 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' From 2f9d8540487f1e560b8da83d39e39eaafd4c48c8 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 27 Mar 2018 12:20:03 +0200 Subject: [PATCH 2/4] Docs for generic error views. --- docs/api-guide/exceptions.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index ba3d5af9b0..dc1294ff8d 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -230,5 +230,32 @@ 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. + +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 From d6583d3aa83d7579c75c42c480b0e20cc83b9f1a Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 28 Mar 2018 08:50:09 +0200 Subject: [PATCH 3/4] Add file encoding for Python 2 --- tests/test_exceptions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index c0ea957941..0c5ff7aae9 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.test import RequestFactory, TestCase From 62415b352e3916bb59192b7fc6f61ab3273d6b41 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 28 Mar 2018 15:45:00 +0200 Subject: [PATCH 4/4] Add comment as per feedback from @tomchristie --- docs/api-guide/exceptions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index dc1294ff8d..d0fc4beaa5 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -236,7 +236,8 @@ By default this exception results in a response with the HTTP status code "400 B # Generic Error Views Django REST Framework provides two error views suitable for providing generic JSON `500` Server Error and -`400` Bad Request responses. +`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].