I’ve been catching up on reading old blog posts (and, by old, I mean older than 6 months) – I’ve sort of been out of the loop lately – and I came across a November 2006 post by Adam Trachtenberg questioning the proper use of HTTP response codes in a Web Service. In particular, he was wondering when it is acceptable to return certain response codes.
I find this particularly interesting (“yes, I am serious”) since I’ve been pondering HTTP response codes and request methods a lot in light of my recent focus on RESTful applications. Adam’s question is closely in line with what I’ve been considering in a recent application (that’s not particularly RESTful).
For example, in this application, a user can set a particular item of content as “private.” That is, only the user has access to view the content on the page. Originally, when unauthorized users viewed the page, they received a 404 Not Found response. However, I didn’t feel this was the correct response to send, since the resource is clearly available on the server, and RFC 2616 states that 404 means “[t]he server has not found anything matching the Request-URI.” In addition, we were actually specifying the reason they could not see the page in the response body, and, again, the RFC states that 404 should be used “when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.” Thus, I opted to use the 403 Forbidden response instead because “[t]he server understood the request, but is refusing to fulfill it” and we are describing “the reason for the refusal in the entity.” Another option is to use an actual 200 OK response and deliver another entity rather than the requested resource. I imagine this is what most applications do. However, I felt that 200 OK signifies to the client that it is actually getting back the requested resource. Since that’s not happening, I wanted the client to know that it wasn’t getting the resource.
Furthermore, we’re using a McAfee HTTP API to do some virus scanning of documents. The API returns a 200 OK response when the document has finished scanning and is free from viruses, but it returns a 406 Not Acceptable response if it encounters a virus. While it doesn’t really matter to me what response code McAfee returns for a failure – what’s important is that they’ve defined what a failed response looks like and I can capture it and take appropriate action – it is interesting to note that the 4xx error codes are not intended to report responses like this. “The 4xx class of status code is intended for cases in which the client seems to have erred.” Clearly, the client did not err in this case; there was no Accept header present for which the resource could not generate a response. Instead, the POSTed file was successfully processed, and while the request was successful, McAfee found a virus and needs to report it to a client. They chose to use 406 to make this clear. Instead, I think they should use 200 OK because the POST request was successful, and the response body should indicate the status of the document (clean or infected).
So, going back to Adam’s post, he questions when to use 4xx responses and when to use 5xx. In general, if the client errs, use 4xx. If the error occurs on the server, use 5xx. However, I would recommend against using these response codes if the server can successfully fulfill the request. HTTP error codes have semantic meaning for clients, and if you apply your own meaning to them, then the client can’t respond appropriately. For example, if you use 400 Bad Request to tell the user that they provided the wrong data and you can’t process the request, then the client assumes that the server it telling it that it sent headers with malformed syntax.
The problem is that developers are attempting to apply HTTP response codes to applications that shouldn’t use HTTP response codes for communication. HTTP response codes are intended for use by HTTP servers communicating with HTTP clients. While we’re using HTTP for transfer of data in our applications, we probably shouldn’t be using the response codes provided in RFC 2616 for anything other than what they are intended since improper use of them might cause some clients to take improper action.
That said, Adam mentions the book RESTful Web Services by Leonard Richardson and Sam Ruby (published just last month). This book includes an appendix explaining when to use each status code. I’ve just ordered it and should receive it in another day or two, so expect another post from me soon continuing my rambling musings on HTTP response codes.