17 December 2012
REST services may not have standards, but they should follow conventions
REST does not define a strict schema or format. It’s more of an architectural style that utilises HTTP and there are few standards for RESTful web services beyond those associated with the underlying protocol. This can give rise to considerable differences in the way that APIs are implemented.
If a service is going to be simple and immediate to work with then it should be predictable. This does not necessariy require an over-zealous and meticulous reading of the finer points of RESTful service design, but a service should conform to some basic conventions.
Resources and addresses
At the heart of a RESTful API is a focus on a resource representation which is accessed by a static URI.
There are no standards over how your URIs should be constructed but common sense should prevail. You don’t have to make your URIs readable or hackable, though using clear terms makes them easier to use. Over-long URIs are often evidence of poor API design so you should avoid clutter in your URIs and ensure that each segment is directly relevant to the resource.
A response should only include the resource that was requested without any extraneous information, such as error messages or status descriptions. It’s important to remember that a URI is a namespace so responses should not use any unnecessary nesting that conceals the requested resource. You can always use HTTP codes to indicate the status of the request.
If you have worked with SOAP based services it can be tempting to design highly structured responses that contain metadata about the response. This can give rise to relatively complex return objects that return status information and error codes. This is not in keeping with a RESTful service where the focus should be on the resource.
In general a response should be as small as possible as this minimises bandwidth usage and therefore improves performance. This also helps to encourage simplicity which makes an API easier to use as integrators do not have to understand complex response structures.
A uniform interface
Web developers will be accustomed to pushing XML and JSON payloads around a network with HTTP, but they may miss some of the nuances around RESTful services. The client application should not need to have any prior knowledge of how to interact with a service beyond a generic understanding of hypermedia and the protocol used by the service. In this context, the HTTP protocol is used to provide a uniform interface for resource manipulation based on methods, status codes and headers. Using a common interface simplifies the overall architecture and improves the clarity of the service interactions, even if it does come at the expense of flexibility.
A URI should identify to a resource and the HTTP method should specify the action that is performed against it. You should always use the standard HTTP methods rather than trying to specify your own non-standard versions. These methods should also behave in the way that an integrator would expect, i.e. use GET to fetch a resource and be clear about the difference between POST and PUT. Methods that are used to query the service and response such as OPTIONS and HEAD should also be provided as people will expect them to be available.
HTTP status codes
A service should use HTTP status codes to indicate status rather than inventing its own system of status and error messages. There is an HTTP status code for pretty much any occasion including successful calls, error states, authentication problems, redirects, resource caching and asynchronous processing. It might be tempting to embellish them or create you own but this should be resisted – it’s not helping developers as you are injecting application specific logic into what should be a uniform interface.
You should use the standard set of HTTP Headers to specify information about the request and response such as the format (Accept), language (Accept-Language) and size (Content-Length). You can specify your own custom headers but note that the convention of appending x- to a custom header has recently been deprecated.
Care should be taken over HTTP header fields, particularly in terms of the implicit assumptions made when they are not supplied. They can become a source of backwards compatibility problems unless clear conventions are followed from the start. For example, if you use the Accept-Language header to specify the locale of the response, make sure that an integrator knows exactly what happens if this header is not supplied.
There’s one convention so important that it is included in the name of the architectural style, i.e. REpresentational State Transfer (REST). A client does not connect directly to a resource, it interacts with a representation of the resource which acts as an abstraction between client and server. Each request should also carry all the contextual information necessary to understand the call.
This means that REST service calls should be stateless so that each request stands on its own. There are no sessions in REST and a service call should not depend on session-related traces left on a server.
This stateless approach has a number of advantages. It helps to improve the visibility of service calls as it becomes easier to understand the context from the request alone. The reliability of a service is enhanced because there are fewer moving parts. It also improves the scalability of services as they are freed from the burden of storing state between requests.
Hypertext-driven APIs and navigable resources
You wouldn’t expect users of a website to piece together the location of an article from a unique identifier. The same should go for the programmable web. Nevertheless, many RESTful APIs are devoid of hyperlinks forcing clients to piece together the URIs for each individual call. This relates to the notion that a RESTful API should be hypertext-driven so that once a user has entered the API from a particular URI any subsequent calls should be driven by choices provided by the server.
For example, a RESTful service that allows you to access the details of available hotel rooms should include a link to the method that allows you to make a booking. In this sense a service is self-describing after the initial request has been made.
Expecting a client to piece together related URIs places a burden on the developer that should be taken care of by the service. A service should allow integrators to navigate around representations via embedded hyperlinks. Not only does it make a service easier to use but it reduces the coupling between a client and server as less specific logic is required to traverse the API.
Conventions are no substitute for documentation
No matter what conventions you follow, integrators will still need accurate and clear documentation. If you are serious about encouraging the integrators to use your API then you will need to provide them with the materials they need to get up and running quickly. You should clearly describe the resources, URIs and methods that your API offers. Well-written code samples should be available in multiple languages. Above all, you will have to keep your documentation up to date as nothing is likely to undermine confidence in an API like dated and inaccurate documentation.