Status Codes for Web Services
Unlike the other posts in this series, this one is quite specific to one type of service – REST – since it deals with status codes, specifically HTTP ones. The ideas are transferrable however and other types of service can return statuses in a similar way.
There’s a few key things to think about when returning status codes. In earlier posts in this series these was discussion of using existing application framework to serve pages and changing the output mechanism accordingly. Usually a web page will return a status 200 for OK or also 302 for found, so this is fine when things are working normally. But when things aren’t going quite so well, its useful to give alternative feedback that can be easily picked up by a client application.
When things go wrong there are a couple of different schools of thought of how the service should respond. One is that if, for example, the user supplies data which fails validation, the service could provide the OK response and a message to the user to let them know what needs validating – exactly as we’d return information messages to a user filling in a form. To be considered restful however, the service should more correctly return one of the “400” status codes, which means that the client made an error. Interesting and useful codes* in this series are:
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 406 Not Acceptable
- 408 Request Timeout
- 417 Expectation Failed
- 418 I’m a teapot
* I didn’t say they were both useful and interesting
Using descriptive status codes allows the client to get the headline of the problem without having to parse a whole request to find out whether it is good or not. HTTP already has this feature built-in, and so we make use of it (HTTP is pretty cool really, makes a great protocol for services!).
Where an error occurs on the server side – it is usual to return a 500 error or another in the 500 series. This lets the client know there is a problem outside of their control; it is useful to include information about whether the client should retry and when. Having a defined protocol for retries helps avoid the situation where a system comes back up only to fall over again with all the traffic from people retrying every minute (or other interval) – this is a real concern for systems that are under heavy load.
Status codes are like a headline to the calling entity about what happened, and are a valuable tool in the web service toolkit. For bonus points, leave me a comment and tell me which is your favourite status code :)
I gather most js libraries will now provide an error handler for 4xx and 5xx, which is quite handy to know whether to display an error dialog. I also use 4xx for when client errors eg when a db constraint fails, I respond with a 4xx and put the error message in the body of the response. For 5xx I log the error message rather than include it in the response.
There is one YUI component however, yui-uploader, which doesn’t seem to treat 4xx as an error on FF for Windows (but it did on a Mac)
A favourite status code? If only we could respond to our managers with status codes when they ask for unreasonable things or don’t give us the full details, any of the 4xx codes would be my favourite ;)
shangxiao: my manager is geeky enough that he’d know perfectly well what I was talking about if I used a 4xx code at him :)
I don’t use errors codes at all.
Custom error pages with description what is happened and recommendation what user need to do – it is my way.
Keep in mind not all users can understood error by number and less of them will know what to do.
Using a HTTP Error code doesn’t stop you serving up a custom error page. In fact thats the best way to do it.
People who visit with a web browser will be none the wiser, but anyone that needs to programatically find out what the server responded with can. And if you’re serving up an API error page by returning HTTP status 200, expect people like me to hunt you down and slap you. *Hard.* Because I check the status code to find out if I hit an error in the API or not, as you’re supposed to. Its a standard for a reason.
I wish there were some more 4xx error codes. They are so arcane and not really fit with today’s use of HTTP as an application protocol.
I would love for some extra codes like missing request parameter, parameter validation failed, etc…
Alexandr: I like to use both – return a status code so anything that cares can see it, then make the body of the thing a sensible error message.
Caius: You are providing us good and sensible advice, thanks for dropping by :)
lifeforms: I have no idea how the codes get decided upon but I do see your point. I end up returning a general error code with a meaningful message usually – the advantage of this is that I can stack error messages and return lots of feedback to the user in one go
For authentication problems, I prefer to use a 412 Precondition Failed. For most of my APIs, I assume that the user is logged in (the Precondition). Although it would be more semantically correct to send the Unauthorized header, I prefer to avoid it since browsers will normally handle it by asking a user to login. Which is confusing and impossible, since my web server is definitely not set up to handle it.
Chris: That’s a good point – it depends what you expect to be consuming your service, sometimes browsers “help” us in the least helpful ways!
Over the summer months I wrote a series of posts about designing APIs in general, and web services in particular. This included posts on status codes for web services, error feedback for web services, auth mechanisms for web services, saving state in web
Roy Fielding, who coined the term “Rest”, suggests using 422 for validation errors: http://tech.groups.yahoo.com/group/rest-discuss/message/6183
I like to verify my pages status code and page info such headers, cookies, with this free tool: http://soft-net.net/SendHTTPTool.aspx
It free and it give you a lot of information about the response from the page.