I am, of course, talking about the RFCs for the Atom Publishing Protocol and Atom Syndication Format, and, during my study and research as I’ve been designing and architecting a RESTful (Representational State Transfer) API based on AtomPub, I’ve found that, while the AtomPub suggests and describes HTTP status codes to use in return for various behaviors, it does not, in fact, define the format of the response entity. The AtomPub even goes so far as to state in Section 5.5:
Implementers are asked to note that according to the HTTP specification, HTTP 4xx and 5xx response entities SHOULD include a human-readable explanation of the error.
Still, it doesn’t describe the format of that “human-readable explanation.”
This led me to do quite a bit of searching, which turned up some old posts on the atom-syntax mailing list that addressed questions about error responses:
On August 2, 2003, Joe Gregoriowrote in response to someone’s question about error repsponses:
You are right that the specification at this time does not cover error
codes. In general the HTTP Status code should be the first line of
defense, such as 403 Not Authorized, etc. There are errors that will
need more detail than just the status code, and I see three possibilities:
Do nothing. That is, let the server decide the error code and
formatting to return it in. For example, when you get a 404 on a
web-site you often get an HTML page or a text/plain document. Not my
favorite option.
Mandate a text/plain result that describes the problem.
The third option is to define an XML format for describing errors, e.g.
<error>
<title></title>
<description></description>
</error>
A few days later (August 8th), Joe asked the question, “How should errors be handled?” Sam Rubyreplied:
I am often (rightfully) accused of being too obtuse. So let me be explicit in what I am suggesting here. Design a pure REST API. Where there seems to be places where “some invention is required”, see if one can reuse precisely those elements - and only those elements - from SOAP. What you will end up with is a fully REST compliant interface which will enjoy wide tooling support.
My first reaction was, “Well, why the hell would I want to use SOAP? I’m trying to be RESTful here!” However, I don’t think what Sam meant was to follow SOAP verbatim but to, rather, borrow from SOAP in much the same way that the Atom community borrowed the WSSE username token from the OASIS Web Services Security committee and adapted it from a specification for SOAP services to a more RESTful application by passing the data through HTTP headers.
Essentially, the implication was to adapt a SOAP Fault to work in a RESTful way.
Diverging from the Atom format and adapting a SOAP format to fit my needs didn’t sit well with me, unfortunately. Rather, as I thought more and more about it, I realized that the Atom format itself suited my needs just fine. So, I decided to use an Atom Entry document that would list an atom:category element for every error that occurred while attempting to process the request (i.e. data validation errors, etc.) and send this back to the user with XHTML in the atom:content element that a client could use to parse and present a human-readable message to their users.
Ultimately, I was happy, could “rest” easy, and the end result looked a bit something like this. This example represents a potential XML entity body of a 400 Bad Request response resulting from invalid data submitted to the Atom service through POST or PUT.
<?xml version="1.0" encoding="utf-8"?>
<entryxmlns="http://www.w3.org/2005/Atom">
<title>An error has occurred</title>
<id>tag:example.org,2008-02:1.0/errors</id>
<updated>2008-02-20T17:08:33Z</updated>
<author>
<name>Ben Ramsey</name>
</author>
<categoryterm="9311"label="Title field missing"scheme="https://api.example.org/1.0/categories/errors"/>
<categoryterm="9301"label="Author field missing"scheme="https://api.example.org/1.0/categories/errors"/>