2

What would be an efficient way to construct error messages during HTTP request parameter validation and serialize them?

Currently, as I have it:

except Section.DoesNotExist:
            return Response(headers = {'INTERNAL_MSG': 'SECTION_NOT_FOUND',
                                       'INTERNAL_CODE': '400'},
                            status = status.HTTP_200_OK)

But, it seems to me this is a not a good way to do it, since I am injecting internal error messages into the HTTP protocol that have nothing to do with HTTP topology.

Preferably, I would like to do something like Twitter, Facebook, and others are doing in their APIs:

{"errors":[{"message":"Sorry, that page does not exist","code":34}]}

So, could you please share your approach to dealing with errors and returning them?

Very much appreciated, thanks!

1 Answer 1

2

Django REST framework handles errors internally and in general does a pretty good job of converting them into reasonable responses that can be parsed by clients. This is done by the internal exception handling, which is open to being extended for special cases.

Usually when you run into a case where an object was specified that does not exist, you raise a 404 Not Found error. Django actually has a helper for this, called get_object_or_404, as it tends to be a very common bit of logic, especially in APIs. Django REST framework will convert this Http404 error that is raised and convert it in to the following response that has a 404 HTTP error code.

{
  "detail": "Not found"
}

Now, this format (and object with a detail key) is not restricted to only Http404 errors, it works for any error that subclasses APIError provided by Django REST framework.

So in your example, you could raise a similar exception by doing

ex = APIError("Section not found")
ex.status_code = 404

raise ex

Or by using get_object_or_404 and letting Django REST framework handle it

from django.shortcuts import get_object_or_404
section = get_object_or_404(Section.objects, pk=1234)

Of course, you can still override the exception handler to format these errors how you want.

def exception_handler(exc):
    from django.http import Http404
    from rest_framework import status

    exc_data = {
        "errors": [],
    }

    if isinstance(exc, Http404):
        exc_data["errors"].append({
            "message": "Sorry that page does not exist",
            "code": 404,
        })
    else if isinstance(exc.detail, list):
        for message in exc.detail:
            exc_data["errors"].append({
                "message": message,
                "code": exc.status_code,
            }
    else:
        exc_data["errors"].append({
            "message": exc.detail,
            "code": exc.status_code,
        })

    return Response(exc_data, status=status.HTTP_200_OK)

Note that this will give all error responses a status code of 200, and embed the actual HTTP status code within the body. This is useful for some applications, but it is usually recommended to only use the 200 status code for success responses.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.