Error Handling In RESTful APIs: Software Engineering 13 Phase 4 Hybrid

Learning Goals


Key Vocab


Introduction

Try as we might, it is impossible to build a robust API without the possibility of errors and exceptions. Common issues include:

  1. Creating records that already exist.
  2. Creating, retrieving, updating, or deleting resources while your database server is down.
  3. Creating or updating records with invalid attributes.
  4. Retrieving, updating, or deleting records that don't exist.

The guiding principle of the REST philosophy is that the behavior of an API should be predictable. So how do we handle these cases outside of the functionality of our API in a predictable way?


HTTP Error Codes

Just like request methods, HTTP also specifies a number of response status codes to help the client understand if and why their request was successful. We've already talked about some status codes in earlier modules:

  1. 200 (OK) means that the request was successful. This can be used for any request method, though it is not always the most descriptive. That being said, the client will be less interested in descriptive codes when requests are successful.
  2. 201 (Created) means that the request was successful in creating a new resource. This is the best code to use after a successful POST request.
  3. 404 (Not Found) means that the request was unsuccessful because it attempted to access a resource that does not exist on the server. After 200, this is the most common status code in a well-built API.

Codes are grouped by the hundreds:

400

The client has made a mistake here in requesting something that does not exist. A 400-class status code- specifically 404- would be most appropriate here.

Let's explore the error codes a bit further:

400-Class Codes: Client Errors

400-class status codes are intended as responses to client errors. These codes can be sent in response to any request method.

Despite their error, it is still our duty as developers (especially RESTful API developers) to give the client an informative message describing what went wrong.

The most common 400-class response codes are:

For more information on 400-class codes, check out the Mozilla documentation Links to an external site..

500-Class Codes: Server Errors

500-class status codes are acknowledgements that the server has produced an error. It is critically important to let the client know that a 500-class error has occurred and whether it is due to regular maintenance, a bug, or a permanent change.

500 (Internal Server Error) is by far the most common 500-class error. It can be appropriately used for nearly every server-side error, and with an appropriate and informative message, it is more than sufficient to meet the client's needs.

That being said, there are several other 500-class status codes for specific cases. For more information on 500-class codes, check out the Mozilla documentation Links to an external site..


Error Handling in Flask

When an error occurs in the runtime of a Flask application, the corresponding status code will be returned to the client. As we've seen in previous lessons, you can also easily set the status code in the construction of a response: it is the optional second argument of the make_response() function. When one of these errors takes place, it is most useful to return a message specific to the application. This is most easily carried out through registering error handlers.

Registering Error Handlers

Similarly to how flask registers routes, error handlers are registered through use of the @app.errorhandler() decorator. Responses are constructed the same as with any other view, either as comma-separated body, status code, headers or an object created with make_response(). (The latter is preferred.)

Let's take a look at a handler for 404s:

This will automatically capture any 404s detected by your Flask application and return the message provided in the response body. Flask can accomplish this because of the werkzeug.exceptions.NotFound class- this is the exception that is raised when a 404 is detected, and we have registered it to our handler. The two are now partnered for life!

werkzeug.exceptions Links to an external site. includes all HTTP 400-class and 500-class codes, and you should think about which are relevant to your API as you build. An HTTP error should never go unhandled, or the client will not know how to proceed with their work.

IMPORTANT: Make sure the messages in your response bodies are as specific as possible! Imagine if Python applications only told you "something went wrong" when there was an error in your code. You'd never figure it out!

Why is it considered a best practice to provide specific error messages when building APIs?

The client needs to know exactly what went wrong.

400-class codes denote that the client made a mistake, so they should inform the client how to avoid that mistake in the future.

500-class codes denote that the server made a mistake, so the client should be informed of this and asked to try again later.


Conclusion

Even the best APIs throw errors- even 500-class errors- sometimes. In order to avoid too many GitHub issues (or worse- people giving up on your API), it's important to register error handlers for every 400- or 500-class status code that might be returned by your API.

Flask makes registration of error handlers very simple through use of the app.errorhandler() decorator. Feeding this the error code exception from werkzeug.exceptions and generating a descriptive response are all you need to do to elevate a simple API to a simple production quality API.


Resources

Powered by Forestry.md