REST stands for Representational State Transfer.
It is an architectural style (or software design pattern) that is used for designing web applications or web services. Well, that is not entirely true, because REST can be used in case of any networked application, but because the overwhelming majority of these are web applications/services, we are going to refer to them in this manner.
When you are using REST to build a web service, you can say that it is a RESTful web service. If you are referring to the API that this web service provides, it’s a RESTful API.
REST Guidelines
REST does not have a specification or concrete rules on how it must be implemented. It is a collection of guidelines that you can use if you would like to develop a RESTful API. You can choose to follow all or just a subset of the guidelines depending on how RESTful you want your API to be.
This approach might become more clear if we compare it to the SOAP communication protocol that is also a commonly used in case of web services. This protocol uses XML format for communication. The request/response formats need to follow strict rules and there is a separate descriptor language called WSDL to describe the formats used by the web service. REST, on the other hand, does not tie your hand regarding what format you should use (XML/JSON, etc.), what should the request or response contain. It is just a set of guidelines to use when building your web service. Although it’s worth mentioning that JSON is the most commonly used format.
So let’s see what are the guidelines that we need to follow if we would like to implement a RESTful web service:
- Objects as resources: Server objects are treated as resources and are exposed using a uniform URL structure and are manipulated using a common set of verbs (HTTP request methods).
- Well chosen HTTP status codes
- Stateless client-server communication
- Representations: Representations of resources are not dependent on which resource we would like to get, but it is determined by the request (with the use of request headers).
- Cacheable resources
Objects as resources
In regular web applications that you can access through your browser, you can usually see URLs that refer to some action like:
- /users/show-profile
- /results/processResults.php
- etc.
As you can see these describe some kind of action, they tell the server what it needs to do.
REST has a quite different approach to this. It does not talk about actions, it talks about resources. Objects on the server side (e.g. blog posts, users etc.) are treated as resources, and you can reference them using a standard URL format. The operation you would like to perform on a resource is determined by the HTTP method that you use.
The purpose of the HTTP methods are:
- GET: Retrieve a resource.
- POST: Create a resource.
- PUT: Update a resource.
- DELETE: Remove a resource.
We can differentiate instance and collection resources depending on whether we are talking about one or more objects. Let’s see some examples of the standard URL structure and the HTTP methods that we can use.
URL | HTTP method | Description |
/messages | GET | Return all the messages. |
/messages/{messageID} | GET | Return a single message. |
/messages | POST | Create a new message. |
/messages/{messageID} | PUT | Update a message. |
/messages/{messageID} | DELETE | Delete a message. |
/messages/{messageID}/likes | GET | Return all the likes for a particular message. |
/messages/{messageID}/likes/{likeID} | GET | Return information about a specific like for a specific message. |
/messages/{messageID}/likes | POST | Create a new like for a particular message. |
/messages/{messageID}/likes/{likeID} | PUT | Update a like for a particular message. |
/messages/{messageID}/likes/{likeID} | DELETE | Delete a like for a particular message. |
/messages/{messageID}/likes | DELETE | Delete all likes for a given message. |
As you can see, some of the URLs are identical, but we are using a different HTTP method, so the server will be able to decide what we would like to do.
HTTP method idempotence
We can say, that an HTTP method is idempotent if issuing the same HTTP request multiple times results in the same outcome as if we have just issued it a single time.
The HTTP methods GET, PUT, DELETE are idempotent, if used properly. Let’s see why:
- Issuing a GET request multiple times will just return the same response multiple times. No issue is caused by this, it can be easily seen. Of course, if the data on the server changes in the meantime, a different result set will be returned.
- If you issue multiple PUT requests, you are updating the resource the same way multiple times to the same state. The end result will be the same as if you would have just made one call.
- Making a DELETE request multiple times won’t cause issues because the requests other than the first one won’t find the resource and will not be able to delete it. So the end result is the same as if there were only one call.
On the other hand, POST is not idempotent as making multiple POST requests with the same content will result in the creating of duplicate resources (with different IDs).
There is catch, however. For the above to be true, you have to design your API correctly. Here are some examples that would violate these idempotence rules and should be avoided when designing a RESTful API:
- You have a GET endpoint that creates a resource. GET should be idempotent, but this case it is not.
- You have a PUT endpoint that allows users increase the amount of votes for a picture. PUT should be idempotent, but in this case it is not.
- Because you increase the votes by incrementing the current vote count, issuing this request multiple times will cause the votes to increase multiple times. Possible solutions:
- Use POST in a RESTful way by creating a new “vote” object every time a user votes.
- Use the less known PATCH HTTP method (not the scope of this tutorial).
Through a final example, you’ll easily see how important it is to keep to these rules. When you are submitting a form using a POST request and try to refresh the browser, you are presented with a message asking if you are sure that you want to issue the same request again. This is because of the fact that POST is not idempotent and issuing it multiple times might cause unwanted side effects like buying two products instead of one. For other HTTP methods, there is no such warning, because they are supposed to be idempotent.
Well chosen HTTP status codes
Becuase REST APIs are consumed by computers and not humans, it is important to always use the proper HTTP status code in the response, so the consumer code is able to decide if the request was successful or not. If the operation failed, the status code can tell some details about the reason of the failure and the client code can use that to decide what should it do (e.g. retry the request).
Stateless client-server communication
In case of REST, the distinction between the client and server is important. These need to be independent of each other, so we can easily scale or relocate them to different servers without affecting the other.
Also, REST relies on a stateless protocol (that is almost always HTTP). This means that every request should contain every information that is needed for the server to process it, so the requests must not depend on anything that was sent by a previous request.
If we take this seriously, we cannot even store anything in the session in a RESTful application, the client has to track this kind of information.
In case of APIs that does not require authentication, this is easily feasible. Most REST APIs, however, use some form of authentication. In this case, no storage on the server side is needed if the clients send their credentials with every request. However, it is not always the best way because in this case we always need to re-authenticate the user. Usually, there is some kind of token generated that the server accepts as authentication for a given amount of time. This slightly violates the stateless principle but some sacrifices have to be made if we would like to make a properly working system.
Representations
Each resource (e.g. blog post) can have many different representations. The most common ones are JSON and XML. REST says that the returned representation of the resource is not dependent on which resource we would like to get back, but on the HTTP request, we send. The request should contain information about what representation we would like to get back.
The headers used are:
- Content-Type: The client and the server both use it to specify the format of the data that is being sent.
- Accept: The client uses this to specify what format it expects from the server.
Cacheable resources
In REST, resources have to be explicitly declared cacheable or not. Caching a resource can eliminate some of the calls to the server as we can just use the locally cached version.
Documenting a REST API
The first step to a good documentation is to follow the REST principle as much as possible. This will allow users to more quickly understand how they can use your API. Of course, you have to create a documentation as well. There are a lot of various ways how you can structure the documentation, here is one example:
- Description of the endpoint
- URL
- HTTP method
- URL parameters
- Data parameters (in request body)
- Request / response format
- Success response
- Error responses
- Sample call
- Notes
REST in the real world
When we refer to REST, it can mean different things. As an example, it can be an API that fully conforms to the REST principles or it can be a web application that only uses some ideas from REST.
For example, we could just have some endpoints in a web application that use the REST URL structure and follows the HTTP method usage guidelines but uses the session to store details about the currently logged in user. This obviously violates the stateless principles, because we are depending on data stored on the server side.