HTTP status codes in REST – best practices

RESTful services are traditionally built over HTTP. The protocol communicates the status of the request by means of HTTP status codes. For a list of status codes – click here

It is difficult to implement all of the status codes in the application but more importantly, it is insane to expose all of these to the consumers of the API. It is important to understand who consumers of your API are. If you own/manage the client(s) that invoke these APIs – then you have some amount of leeway to go crazy with the status codes, on the other hand if you are exposing your API to be consumed by other tool builders/mashup component developers then it makes it difficult for them to identify success/failure.

The best approach is to limit the number of status codes exposed to a handful. There is nothing set in stone as to what it should be. But here is one such sample in Java that describes an enum that exposes the HTTP status codes to the client

public enum HttpResponseTypes {

	  ,OK(200)
	  ,CREATED(201)
	  ,BAD_REQUEST(400);	  
	  ,NOT_FOUND(404)
	  ,FORBIDDEN(403)
	  ,ERROR(500)	  

	int code = 500;

	HttpResponseTypes (int _statusCode ) {
		 this.code = _statusCode ;
	}

	public int statusCode() {
		return this.code ;
	}

}

Why pick this list?

In a typical call here is what we would like to communicate the following:

  • Everything is good (OK)
  • The input from the client was bad (BAD_REQUEST)
  • Something happened on the server & the request could not be processed (ERROR)
  • Client is not supposed to access that resource/entity/etc..(FORBIDDEN)
  • Client requested for something that is not available. (NOT_FOUND)
  • I threw in CREATED(201) to indicate the success of POST/PUT operation for CREATE requests.

    Now your clients can take action based on these HTTP codes and implement them fairly easily. Over a lot of implementations, I have found this is the minimal set that is easy to communicate & works for a broad range of use cases.

    Caution!! – This is not the be-all end-all, just sending HTTP status codes is not going to help. This needs to be ‘ALWAYS‘ augmented with descriptive messages that indicate

    * What happened?
    * What action to take if an error was encountered? (retryable/ignore etc..)
    * Hints on how to fix the problem (esp if it is a bad client request)

    Here are some examples of suggestions:

       
        "messages": [ "response": 
                      { "message": "Request was processed successfully"
                        "isSuccess" : true
                        "statusCode" : "200"
                        "statusDescription" : "OK"
                      }
                    ]
    
        "messages": [ "response": 
                     { "message": "Missing index parameter in request. Resubmit with 0 < index < 300"
                    "isSuccess" : false
                    "statusCode" : "400"
                    "statusDescription" : "BAD_REQUEST"
                     } 
                   ]
    

    Strictness

    Some API developers punish the clients badly by having them to strictly adhere to the HTTP codes and mandating that the clients use them. There are some technical limitations around certain implementations of REST client libraries & containers that do not comprehend the HTTP error codes correctly or fire an interceptor to handle the error before the client can get a hold of the response. In such situations, it is better to support a standard attribute with all API calls.

    An example of it would be supressHttpStatusCodes or ignore_http_status_codes which take boolean parameter and if set will always send HTTP status code 200 (OK). Having the statusCode and message attributes in the response, would help the application build logic around them.

    Twitter API has something like this.

    Recommendations:

  • REST services are to be be developed top-down.
  • Fix on the list of status codes that you plan to send and stick with it. Frequently changing the status codes and your perceived understanding of how clients ought to treat it will cause more confusion amongst the client developers (for instance: 412 – Precondition Failed)
  • Look at the API exposed by companies that have a huge user base (think Twitter, LinkedIn, Foursquare, Flickr …) and learn how they do it. Most of learned their lessons the hard way and they have a myriad of operations that you can perform on entities and most likely will cover most of your use cases
  • .

    Advertisements

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s

    %d bloggers like this: