Implementing API Exceptions

It’s very common to implement RESTful APIs on top of Flask. One of thefirst things that developers run into is the realization that the builtinexceptions are not expressive enough for APIs and that the content type oftext/html they are emitting is not very useful for API consumers.

The better solution than using abort to signal errors for invalid APIusage is to implement your own exception type and install an error handlerfor it that produces the errors in the format the user is expecting.

Simple Exception Class

The basic idea is to introduce a new exception that can take a properhuman readable message, a status code for the error and some optionalpayload to give more context for the error.

This is a simple example:

  1. from flask import jsonify
  2.  
  3. class InvalidUsage(Exception):
  4. status_code = 400
  5.  
  6. def __init__(self, message, status_code=None, payload=None):
  7. Exception.__init__(self)
  8. self.message = message
  9. if status_code is not None:
  10. self.status_code = status_code
  11. self.payload = payload
  12.  
  13. def to_dict(self):
  14. rv = dict(self.payload or ())
  15. rv['message'] = self.message
  16. return rv

A view can now raise that exception with an error message. Additionallysome extra payload can be provided as a dictionary through the _payload_parameter.

Registering an Error Handler

At that point views can raise that error, but it would immediately resultin an internal server error. The reason for this is that there is nohandler registered for this error class. That however is easy to add:

  1. @app.errorhandler(InvalidUsage)def handle_invalid_usage(error): response = jsonify(error.to_dict()) response.status_code = error.status_code return response

Usage in Views

Here is how a view can use that functionality:

  1. @app.route('/foo')def get_foo(): raise InvalidUsage('This view is gone', status_code=410)