RESTful API Best Practices

The past few days I have read a number of articles outlining what they feel are best practices when designing RESTful APIs. I have put together some of the most common points that I feel directly impact good API design. This post is a work in progress, and will evolve as I dive deeper into the world of good API design.

Nouns, not Verbs

A good API starts with its structure. The consumer of most APIs tend to be developers, so consistency and a nice interface goes a long way. The first step in good API design is having a good resource naming scheme. Too often people intermingle verbs with their resource names. A good API should be noun-based, and the verbs should be represented by HTTP methods.

Bad: GET /api/getProducts
Good: GET /api/products

API Versions

API versioning can be a point of contention. There are good and bad uses, and there are also appropriate and inappropriate time to make use of versioning. I feel that a well-designed API should not require a version, and that it is beneficial to maintain a consistent API through versions. That said, there are many cases where versioning is necessary such as major architectural changes, or paying customers who may not be able to keep their applications in lock step with your own. If you are going to make use of versioning in your API, do so in the URL and not in the header. All versions should be explorable, making headers a non-ideal option. Minor revisions can be expressed using special headers, and can also be expressed by adding new fields while leaving existing fields unchanged.

URL: /api/v1/products/1

Plural or Singular

I have no strong feelings on plural versus singular naming, however the communal wisdom dictates that all resource locators should be plural in name. Regardless of what format you choose, be consistent throughout the application.

Bad: /api/products/1, /api/item/2
Good: /api/products/1, /api/items/2

Nested Resources

Nested resources should only be created when there is a clear relationship between the two resources. It can be used to package convenience methods such as commonly made queries, and it can be used for filtering or sub-selection. The import concept to note is that nested routing should be refining a resource always.

Bad: /api/song/1/album/2
Good: /api/album2/song/1

GET/HEAD/POST/PUT/DELETE

There is not much to say here – use the HTTP verbs whenever possible! They make your code easy to read and API easy to consume. There are some caveats which must be considered, such as proxies which prevent requests other than GET or POST, but for these, make use of a convention of setting a POST header which your software can decode and route appropriately.

Action Method
Retrieve an existing resource GET /api/products/1
Update an existing resource PUT /api/products/1
Create a new resource POST /api/products/1
Delete an existing resource DELETE /api/products/1

Status Codes

Whenever dealing with resources, always make sure you return an appropriate status code that follows standards. Most individuals are used to returning HTTP 200 OK or HTTP 400 BAD REQUEST  for their applications, but for not much additional cost you can provide a lot more semantic meaning in your application.

201 CREATED – Whenever a resource has been created. Include a URL to the new resource.
202 ACCEPTED – Let the user know their resource has been accepted for processing.
204 NO CONTENT – Let the user know the request succeeded, but the server has nothing to say (i.e. responding to a DELETE request).

Error Codes

Continuing the discussion about status codes: we also need to tell the user when things didn’t go so well. It is particularly important that your format your response consistently, correctly, and provide as much detail as possible. Often times, this is the only way that developers will be able to interact with your system and get meaningful information back.

400 BAD REQUEST – Malformed request payload such as invalid XML or JSON.
410 GONE – When a resource endpoint has been deprecated.
415 UNSUPPORTED MEDIA TYPE – When a content type was either incorrectly provided or the server cannot handle that content type.
422 UNPROCESSABLE ENTITY – When the request fails server-side validation.

Payloads

Payload type doesn’t matter in a real sense. Almost every framework and language will support the most common options: JSON and XML. I personally recommend choosing JSON as XML is unnecessarily verbose and has well known parsing problems. If you are going to support multiple types, I recommend going the Rails route and appending the type to the URL such as .xml or .json. This allows for browser explorability and simple visual inspection of the expected payload types.

Security

In this day and age, it is unacceptable to not be using SSL. The overhead cost of SSL is trivial, and the security it can provide is invaluable. Certificates are cheap, and allow for the secure transmission of tokens, authentication, and of course your data.

Night of the Living Dead – Tombstoning Your Code

As code bases grow in size, so does the amount of cruft accumulated from years of refactoring, improvement, or feature abandonment. Dead code can become troublesome to troubleshoot, introduce potential security risks, and confuse developers who continue to work. In an ideal world we would do a simple grep the code base to find references to its use, and if none come up, prune the code. Unfortunately in the real world, this breaks down pretty quickly as people can do some pretty tricky things that make code usefulness non-obvious:

  • Dynamic code generation – generating the path or dependency names automatically at run time (getters/setters, importing name spaces)
  • External dependencies – projects external to the code base that may depend on some legacy components

There is an interesting idea from David Schnepper from Box who talks about the idea of “tombstones” in the code base. The core idea is that all methods in a code base be instrumented with a simple action called a tombstone such as “Tombstone(‘2014-10-31’)” that are both logged and automatically removed from the code when the code path is determined to be live. Over time, tombstones of dead code will remain which indicates that it is likely safe to remove the zombie code from the code base.

While this is a fantastic idea for deprecating dead code, I don’t think that this is ideal for a production system. There are a number of things to consider when deprecating code in this manner:

  • What is the performance impact of adding a tombstone to my application?
  • How do you determine an acceptable tombstone purge date? A month? A year?
  • What risk does this introduce in third party integration or other dependent services?
  • How do you handle cross-project dependencies?

Applied correctly though I think that adding tombstones is an interesting idea, one that perhaps could be automated with solid code instrumentation.

DupliFinder Alpha Release

As promised, here is a compiled installer as well as the Visual C# 2008 source code for your enjoyment. A few things to note: I can’t guarantee that it will work on your system, I can’t guarantee that it will work as advertised, and that all crashes have a reason. For developers I can’t guarantee that the source code is readable :). Hopefully you’ll see through my poor commenting and naming conventions and see the potential for this code :P. Anyways, this is by no means a finished product, but I am releasing it to one keep myself on schedule, and two make a duplicate file finding program available for free (finally!). The installer may only be 64-bit (the publish options in Visual Studio are so confusing!) so if that’s the case you will need to compile it yourself. Mature releases will have a 64 and 32-bit build available (with probably a real and better install system).

As usual, please leave feedback relating to functionality or utter destruction in the comments below, and remember it’s alpha software so use at your own risk! It won’t delete random files, but don’t think it won’t actually delete all the files when you select them with the checkbox and choose Erase!

In Development Land Again: DupliFinder, Duplicate Image Removal

Interesting enough, the more stressed I become the more I desire to program. And not just random programming, but programming to solve a problem (namely one of me :)). What I’ve been working on over the past couple days is a nice Windows utility to work with and manage duplicate files. Right now it works on the head of the file (64KB) or entire file for comparison, but future versions (such as the one I’m working on now) are going to include audio stream matching (to compare audio regardless of the format or compression) and video frame matching along with a host of other options. Here’s a screen shot of it in action:

DupliFinder Duplicate File Finder

DupliFinder Duplicate File Finder

As you can see the UI is almost complete, allowing you to select a root folder and you can scan current and sub directories optionally. The only problem with it at the moment is it’s single-threaded, so when it is given a large folder to process it feels as if the program has frozen, but don’t worry it’s crunching away in the background.

The feature I’m adding right now is a preview/compare pane for easy verification that the file is the same, as well as giving the user to option to delete the “duplicate” or “original” in case of file confusion. This will be ready to go for the v1.0 release of the utility.

If anyone is interested, I can package up a preview version that has some quirks and the single-threaded problem. I had looked all over for a program that would allow you to delete duplicate images and other files and it’s ridiculous the amount of money those scam-like software companies try and charge for such simple (but effective) software! Anyways I’m contributing back to the community by releasing this under GPLv2. On top of handling photos (for which I’ve seen some software cost $30US!) it will handle all sorts of stream and data related information.

For any programmers out there reading this, it was programmed using Visual C# 2008 on a Windows 7 development box, so all sorts of shiny Windows 7 features may start peeking through soon :).

If you have any comments, please feel free to leave them below, and if you would like to play with the source or the compiled version of this app, just let me know in the comments and I will fire off some more information and a package. That’s all for now!