I see a fair amount of confusion with services over developers returning incorrect or incomplete HTTP failure codes from their RESTful controller actions, so here’s a quick reference to some of the most commonly-used codes in the 400 range and their specific use in a Rails context.
|401||:unauthorized||The requester is not authorized to access this resource. Useful if you’re trying to roll some form of RESTful authentication (e.g. see Amazon’s S3 authentication).|
|404||:not_found||The request is trying to access a resource that does not exist. Use this when your find method raises ActiveRecord::RecordNotFound, or your find_by returns nil.|
|405||:method_not_allowed||The request is asking to perform a CRUD operation that your resource doesn’t support. It’s certainly much friendlier than bombing out because you haven’t defined a create method on your controller.|
|406||:not_acceptable||The request is trying to access a resource in a format that your server doesn’t support. If a request doesn’t match any format you’ve provided in your respond_to block, Rails will automatically respond with this and an empty body (see ActionController::MimeResponds).|
|408||:request_timeout||The timestamp on the request doesn’t match up to the server. Useful for authenticating requests that an attacker can’t play back at a later time.|
|409||:conflict||The POST or PUT performed on your resource comes into conflict with an existing resource. Use this when your model fails a uniqueness_of validation. The easiest way to discover this is to compare the contents of the model error messages against ActiveRecord::Errors.default_error_messages[:taken].|
|422||:unprocessable_entity||The request was correct but contains incorrect data, as with a regular model validation failure on a PUT or POST.|
These are all the codes I’ve used in my RESTful services, but if you know of any others that I’ve missed post them in the comments or send me an email and I’ll incorporate them into the table above.
Also, it’s worth noting that REST, based as it is on the HTTP we know and love, is supposed to be reasonably human-friendly. In my opinion it’s not necessary to adhere strictly to the above conventions (although I try to) as long as the human beings trying to use your service understand why their requests failed and what they can do to fix them.
This is part of a series of posts on Rails and REST. Read the rest.