Designing Restful Web Services
What are the restful web services?
REST is acronym for REpresentational State Transfer. Restful Web Services is a stateless client-server architecture where web services are resources and can be identified by their URIs. (Remember you should treat every object in your application as Resource)
Designing a robust REST API requires a minimum of the following activities
Every resource should be identified by its URL’s.
To perform different operations use appropriate http methods along with resource URL.
Determine the resources;
Create a resource model;
Formalize the resource model as an object model;
Create JSON schemas (if using JSON) of the resources;
Write a list of actions to be performed on the resources;
Translate the object model into URLs;
Map the actions to HTTP methods and query parameters;
Using HTTP Methods for RESTful Services
The HTTP verbs comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, PATCH, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other verbs, too, but are utilized less frequently. Of those less-frequent methods, OPTIONS and HEAD are used more often than others.
Below is a table summarizing recommended return values of the primary HTTP methods in combination with the resource URIs:
Example of Building a RESTful Web Service using spring
Design Rules
Before continuing with our design tasks, let’s pause to consider a few best practices when developing a RESTful API. These practices will help us construct a robust yet straightforward API and help with the next design steps we undertake. The following are standard best practices espoused on many websites discussing Restful API design.
- Use nouns to represent resources, plural for collections, singular for a single resource.
- HTTP request methods define actions performed on resources.
- All resources and communication are stateless.
- Specify a version number for your API.
- Forward-slashes represent a hierarchical relationship.
- Use hyphens rather than underscores in URIs.
- Prefer lower-case letters in REST URIs.
- Never include file extensions to indicate file types in URIs.
- Use query component variables in a URI to filter collections.
Nouns not Verbs
Remember, REST is an architecture for requesting HTTP actions to be performed against resources. Resources are objects; nouns represent objects. A URI is the resource’s identifier, while a URL is a resource’s identity and location. This distinction between resource and action is essential, as when developing a RESTful API, you should avoid an RPC style API. If not sure of the difference, the following two URLs illustrate an RPC API using a verb compared to a RESTful API using a noun.
// using a verb - RPC Style
http://www.nowhere.com/imageclient/getClientsById
// using a noun - RESTful
http://www.nowhere.com/imageClient/{client-id}
This distinction between nouns and verbs will be more apparent when we determine our API’s resource URLs.
- Note that we use the terms URL and URI interchangeably. Although technically different, as a URI, is only an identifier and not a location while a URL is both (hence URI and URL), here we treat both terms as synonymous.
HTTP Request Methods Define Actions
Use HTTP request methods to manipulate resources. Do not define your own. The following table lists the most commonly used HTTP request methods.
What this means is that the same URL that identifies a resource can perform different actions on that resource. Consider the difference the HTTP request method makes to the same URL.
If you are accustomed to developing RPC style APIs, then using an HTTP request method to distinguish between the action to take on a resource might seem confusing. However, it will become more intuitive as you become comfortable with RESTful API design.
Corollary Antipattern
Do not do the following, as this is a common antipattern when developing a RESTful API. It might seem easy to succumb to the seductive convenience of turning a RESTful API into an RPC API, but I promise, it only leads to confusion later. An RPC-style “RESTful API” such as the following, is harder for developers of external systems to understand and makes your API is harder to maintain. The creators of the HTTP methods are most likely smarter than you or I, trust their judgment and stick to the HTTP methods.
Resources Must be Stateless
Resources must be stateless. If familiar with more traditional web development, then this might seem a problematic edict. Yes, it requires not using cookies, URL parameters, and session variables to maintain state. But consider this, these constructs are all schemes to try avoiding the harsh reality of the web, namely, that the Internet is stateless. But REST embraces the statelessness of the Internet and admits that these schemes all try to circumvent this reality of statelessness. So if you are designing a RESTful API, design it as a stateless system. Of course, a client sometimes requires that it maintain state, but if it does, then the client and not the server should maintain state. A server must know nothing of a client’s statefulness. A RESTful API is stateless.
Represent Resources as Hierarchical Relationships
Resources are hierarchical. REST interfaces should reflect this hierarchy. A well-designed hierarchical path makes your API easy to understand. The following object model and its translation to URLs illustrates a RESTful hierarchy.
We can translate these resources, and their relationships, into a hierarchy,
- a government is a collection of agency resources,
- an agency is a collection of department resources,
- and a department is a collection of employee resources.
We can translate the object model just created into the hierarchical URIs in the following table.
Specify a Version
Well designed REST APIs should include a version. Imagine the horror clients of your API will have if you were to suddenly change your REST API; all systems consuming your REST API endpoints would break. To avoid this problem, version your application so your APIs can continue to work with your old API and then orderly transition to your new API. The four common methods to version your API are to
- add the version to the URI,
- create a custom request header,
- append a query parameter,
- and change the accept header.
Versioning in URI
One technique for versioning is to add it directly to your API’s URL. For example, the following illustrates using versioning in an API’s URL.
When you use the version number in the URL, the client is requesting a different resource. Some claim using a version in the URL is technically violating RESTful architecture, as a URI is supposed to be a resource identifier, and adding a version breaks that contract. However, using a URI with a version is a common and pragmatic means of versioning a RESTful API.
Versioning in Header
Another technique for versioning is to add the version to the Http header of your HTTP request as a custom header, or using an accept header. These are also common techniques; for example, you might add a header that has the following value.
Accept-API-Version: resource=2.0
Versioning can be a contentious topic when discussing RESTful APIs. But the answer is to pragmatically research and choose the technique most useful to your particular circumstance.
- Versioning using custom Accept header (Versioning REST APIs with a custom Accept header in Jersey).
- Versioning using version in URI (Versioning web-services with Java EE).
- List of versioning techniques used by major websites (How are REST APIs versioned?).
For most of this tutorial, we do not version our API; however, we will cover an easy technique you can use to version your API if your API doesn’t change often.