Where you have software, you have errors. Web services are no exception. When talking about the design of RESTful web services, a problem quickly rears its head:
HTTP Status Codes are Pretty Inflexible
Since we’re following RESTful principles here, we already have a tool to communicate these errors: the HTTP status code. Now – this is a pretty good system as far as the transport protocol goes, and the formally defined codes available cover lots of the generic cases such as “I just don’t know what you’re asking for” and “I can’t let you see that.”
But I’m pretty sure you see the problem. My service for letting instructors grade a student’s homework may choke on a request that tries to set the grade to ‘4.2’ and there’s no HTTP status code for “Grades don’t go that high.” Some people have tried to extend or build on top of HTTP to cover some important domains but you can’t cover everything (or get everyone to use your extension).
Luckily, HTTP accounts for this with some general status codes such as “400 – The request could not be understood.” HTTP recommends that you provide not only a status code of 400 but a document body that describes the error. When a client sees a 400, it can dive into that payload to get more information.
The ROA Technology group recently looked at the error documents that a variety of services produce, and found that the approaches were quite similar. Based on examples from the Student Web Service, Catalyst, and Amazon’s Web Services offerings, we would like to offer the following recommendation.
The format should be easily parseable. We recommend XHTML because of the huge number of tools that know how to parse and display it, but many other formats would do just as well.
Three distinct elements for three distinct audiences. Three types of viewers will probably see your error messages: HTTP clients that are actually doing the transport, programmatic client code that understand the content or purpose of the service, and humans who are programming to, debuging, or using your service. So:
- error_http_code Include the numeric HTTP status code used to report this error. Anything that knows how to react to generic HTTP codes will thank you.
- error_key A short, unique string that identifies the error. This should be used to allow client code to programmatically react to errors in at a more granular level than the HTTP status code. These should remain as static as possible to avoid breaking code!
- error_description A human-readable chunk of text or hypertext intended to help a user of the service identify and resolve the error.
These documents could be extended with new elements. Your service might have good reason to include other useful bits of information, and we encourage this as appropriate.
Recommendations without examples are no good, so:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>InvalidHomeworkScore</title> </head> <body> <div class="error_http_status">400</div> <div class="error_key">InvalidHomeworkScore</div> <div class="error_description"> The score you included in your request was not within the acceptable range of 0 - 100 points. <br/> Please refer to the <a rel="documentation" href="http://example.com/scoring-docs">scoring documentation</a>. </div> </body> </html>
Great! Now, my HTTP library can avoid caching this since it’s an error, my client code can notice “InvalidHomeworkScore” and tell my end user that they need to try again, and when I was programming my client, it was easy for me to figure out what the heck was going wrong.