Discussing RESTful services
REST stands for representational state transfer. It is an architectural style that defines a set of guidelines for building web services.
What is an architectural style? It's nothing but a concept with predefined principles. We will talk about these principles in a moment. When you follow REST, you are actually implementing the principles that are the building blocks of REST in your application.
However, the implementation of REST will definitely differ from developer to developer. There is no fixed implementation style. Don't get confused with architectural patterns, which are not concepts but the actual implementations. MVC is an architectural pattern as it has a fixed structure that defines how the components interact with each other where they can't be differently implemented.
The following is a very simple diagram of a REST-based service:

To simplify things, consider the preceding diagram, which shows you a service that has certain methods, such as GET
, POST
, PUT
, and DELETE
. That is what this style is all about. When you design your service, which will have all these methods—with the intended operations inside them—we can consider it as a REST-based service, otherwise known as a RESTful service. More importantly, the service can be called from an application built in any platform and language as the service has a standard architecture.
As discussed, a RESTful service is a service that supports REST. Let's talk about the characteristics of REST so that we can understand what is expected from a service that is RESTful.
REST characteristics
The main building blocks of web services are the client and server architectures. The response sent from the server is actually a reply to the client's request. It's like you are asking a question and the server responds if it finds the answer. The response that comes from the server is actually a resource in a certain format or representation. The formats that are usually seen are .json
, .xml
, .pdf
, .doc
, and so on.
REST is stateless. Stateless means that the state of the system is always different. So, when a request comes to the server, it is served and forgotten. Thus, the next request does not depend on the state of the previous one. Each request is handled by the server independently.
The requests are performed in an HTTP connection. They each take the form of a uniform resource identifier (URI). This identifier helps us to locate the required resource on the web server.
Roy Fielding’s PhD dissertation, entitled Architectural Styles and the Design of Network-Based Software Architectures, defined REST. The following are some key points extracted from his research:
- Like many distributed architectures, REST imposes layers, statelessness, and caching.
- REST improves efficiency, interoperability, and overall performance.
- REST introduces uniformity by following a set of rules on how to identify and manipulate resources, along with the process to simplify the description about its operations through metadata so that the messages passed will be self-explanatory. We will talk more about this uniformity, which is called the uniform interface.
- As REST is an architectural style, a service can be developed using any language or platform as long as it supports HTTP.
Note
You can read the whole dissertation at https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm.
Resource-oriented architecture
Every resource on the web has been given a unique identifier, otherwise known as a URI. The uniform resource locator (URL) is the most common type of URI used on the web today. The URLhttps://www.packtpub.com/ identifies and locates the Packt Publishing site.
Let's look at a quick picture of the architecture. In the following diagram, a client is trying to access a resource through an identifier (URL). The resource is present on the server and has a representation that can be returned to the client when requested:

As the name suggests, the URL is something that is tied to only one resource; therefore, if I want to point someone to one resource, I can easily share that identifier in email, chat, and so on.
These identifiers can by easily remembered if they are named with company or resource names. The best example is www.google.com, which is very easy to remember as the name Google is present. Therefore, we can spread the resource link by word of mouth and you can enter it into a web browser, such as Chrome or Firefox, within seconds.
You might find hyperlinks on a particular web page that link to another website for another resource. That means that resources are now interconnected because of the hyperlinks.
These interconnected resources form the resource-oriented architecture. Hyperlinks make it easy to navigate from one resource to another by using the target resource URI.
Note
For example, in HTML, you link to another resource through the anchor element. The following is one anchor element that links to Packt's IoT book catalog page:<a href="https://www.packtpub.com/tech/Internet%20of%20
Things">Packt IoT Books</a>
By default, the anchor element is rendered as an underlined text. When you hover over it, you can see the attached URI at the bottom, as shown in the following screenshot:

You can click on the anchor text (Packt IoT Books
), which then fires a GET
request for the target resource URI.
Note that the moment you click the hyperlink, you will land on a web page that is actually a representation of a resource. The most common representation you will encounter is in HTML format. Some other common formats are (X)HTML, JPEG, GIF, WMV, SWF, RSS, ATOM, CSS, JavaScript/JSON, and so on. When a browser receives one of these representations, it tries to parse it and then renders it for viewing, if parsing succeeds.
URI
We have talked a lot about resources. They are actually the pages that we see on a particular website. However, resources in HTTP are not just simple files in the form of HTML web pages. Generally, a resource is defined as any piece of information that can be uniquely identified by a URI, such as http://packtpub.com/.
Let's talk about URIs for a moment. A URI consists of a few components: a URI scheme name, such as http
or ftp
is the first part, followed by a colon character. After the colon character comes the hierarchical part:
<scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]
Let's analyze one URI:
https://www.flipkart.com/men/tshirts/pr?sid=2oq%2Cs9b%2Cj9y
Let's break down the preceding URI:
- The scheme name is
https
. - The scheme name is followed by the hierarchical part,
//www.flipkart.com/men/tshirts/pr
. The hierarchical part starts with//
. - The hierarchical part also contains an optional query, which is
sid=2oq%2Cs9b%2Cj9y
, in this case.
The following is an example of a URI containing the optional fragment part:
https://en.wikipedia.org/wiki/Packt#PacktLib
REST constraints
REST is defined by six constraints, as shown in the following diagram. One of them is optional:

Each of these constraints enforce a design decision for the service that is to be followed. If it is not followed, the service can't be denoted as RESTful. Let's discuss these constraints one by one.
Client-server architecture
The client or the consumer of the service should not worry about how the server processes the data and stores it in the database. Similarly, the server does not need to depend on the client's implementation, especially the UI.
Think of an internet of things device or sensor that doesn't have much of a UI. However, it interacts with the server to store data using APIs, which are programmed to be fired on specific events. Suppose you are using an IoT device that alerts you when your car runs out of petrol. At the time of a petrol shortage detection by the sensor in the IoT device, it calls the configured API, which then finally sends an alert to the owner.
What that means is that the client and server are not one entity and each can live without the other. They can be designed and evolved independently. Now you might ask, How can a client work without knowing about the server's architecture, and vice versa?Well, that is what these constraints are meant for. The service, when interacted with by the clients, provides enough information about its nature: how to consume it, and what operations you can carry out using it.
As we go ahead in this section, you will realize that there is absolutely no relation between the client and the server, and they can be completely decoupled if they adhere to all these constraints perfectly.
Stateless
The term stateless means that the state in which the application remains for a particular time may not persist to the next moment. A RESTful service does not maintain the application's state, and thus it is stateless.
A request in a RESTful service does not depend on a past request. The service treats each request independently. On the other hand, a stateful service needs to record the application's current state when the request is performed so that it can act as required for the next request.
Moreover, because of an absence of these complications, stateless services become very easy to host. As we need not worry about the state of the application, it becomes easy to implement, and maintenance becomes smooth.
Caching
To avoid generating the same data with every request, there is a technique called caching that is used to store the data either on the client's or the server's side. This cached data may be used for further reference whenever it is required.
When using caching, it is important that you manage it properly. The reason for this is simple. We are storing data that won't be replaced by fresh data from the server. While this is an advantage that increases the performance of the service, at the same time, if we are not careful as to what to cache and configure during its lifetime, we might end up seeing outdated data. For example, suppose we are showing the live price of gold on our website and we cached this figure. The next time the price changes, it won't be reflected unless we expire the cache that was previously stored.
Let's look at the different kinds of HTTP headers and how to configure caches:
Header | Application |
Date | Date and time of the generation of the representation. |
Last modified | Date and time when this representation was last modified by the server. |
Cache-control | The HTTP 1.1 header used to control caching. We will look at this in more detail after this table. |
Expires | This header helps to tag an expiration date and time for this representation. |
Age | Denotes the time in seconds since the representation was fetched from the server. |
The configuration of the preceding five headers depends upon the nature of the service. Take the example of the service that provides the live price of gold—ideally, it would have the cache age limit as low as possible, or even have caching turned off, because users should see the latest results every time they refer to the site.
However, a site that contains many images would hardly change or update them. In that case, the cache can be configured to store them for a longer duration.
These header values are consulted in accordance with the cache-control header to check whether the cached results are still valid or not.
The following are the most common values for the cache-control header:
Directive | Application |
Public | This is the default directive. This allows every component to cache the representation. |
Private | Only the client or server can cache the representation. However, intermediary components are restricted. |
no-cache/no-store | With this value, we can turn off caching. |
max-age | This value is the time in seconds after the date and time is mentioned in the Date header, which denotes the validity of the representation. |
s-maxage | This does the same as max-age, but only targets intermediary caching. |
must-revalidate | This states that the representation must be revalidated if the max-age has passed. |
proxy-validate | This does the same as max-revalidate, but only targets intermediary caching. |
Code on demand (optional)
As the phrase code on demand suggests, the service may try to execute code on the client to extend the functionality. However, this is optional, and not every service does this.
Consider an example of a web application that calls a ticketing service to fetch all the available tickets. The service wants always to show this information in an alert. In order to do this, the service can return a JavaScript code along with the data, which has an alert message with the number of available tickets. Thus, as soon as the client receives the response from the service, an alert is executed and the data is shown.
Uniform interface
When we encounter the word interface, the first thing that comes to our mind is decoupling. We create interfaces to have loosely coupled architecture, and the same type of architecture is seen in the case of RESTful.
While implementing REST, we use the same concept to decouple the client from the implementation of the REST service. However, to implement such a decoupling between the client and the service, standards are defined that every RESTful service supports.
Note the word standard in the preceding line. We have so many services in the world and, obviously, the consumers outnumber the services. As a result, we have to follow some rules while designing the services because every client should understand the service easily without any hassle.
REST is defined by four interface constraints:
- Identification of resources: A URI is used to identify a resource. The resource is a web document.
- Manipulation of resources through representations: When a client has a given resource—along with any metadata—they should have enough information to either modify or delete the resource. So, for example,
GET
means that you want to retrieve data about the URI-identified resource. You can describe an operation with anHTTP
method and a URI. - Self-descriptive messages: The messages passed should contain enough information about the data to be understood and processed for further operations. MIME types are used for this purpose.
- Hypermedia as the engine of the application state (HATEOAS): The representation returned from the service should contain all the future actions as links. It is the same as visiting a website in which you find different hyperlinks providing you with the different types of available operations.
HTTP 1.1 provides a set of methods, called verbs. Implementing these verbs in our services would mark them as standardized. The important verbs are as follows:
Method | Operation Performed on Server | Method Type |
| Read/retrieve a resource. | Safe |
| Either insert a new resource or update the resource if it already exists. | Idempotent |
| Insert a new resource. Can be used to update an existing resource as well. | Nonidempotent |
| Delete a resource . | Idempotent |
| Get a list of all the allowed operations for a resource. | Safe |
| Return only the response headers with no response body. | Safe |
The preceding table is quite self-explanatory, except the Method Type column. Let me clarify this.
A safe operation when performed on the service does not have any effect on the original value of the resource. As the GET
, OPTIONS
, and HEAD
verbs only retrieve or read the resource-related stuff and does not update that, they are safe.
An idempotent (can be repeated) operation when performed gives the same result no matter how many times we perform it. For example, when you make a DELETE
or PUT
operation, you are actually operating on a particular resource, and the operation can be repeated with no issues.
Note
POST
versus PUT
: This is a very common topic of discussion on the internet, and one that is very easy to understand. Both POST
andPUT
can be used to insert or update a resource. However, POST
is nonidempotent, meaning that it isn't repeatable. The reason is that each time you call using POST
, it will create a new resource if you don't provide the exact URI of the resource. The next time you use POST
, it will again create a new resource. However, inPUT
, it will first validate the existence of the resource. If it exists, it will update it; otherwise, it will create it.
More explanation
Among all the available methods, GET
is the most popular one, as it is used to fetch the resource.
The HEAD
method will only return the response headers with an empty body. This is mostly only required when we don't need the whole representation of the resource.
The OPTIONS
method is used to get a list of the allowed or available operations on the resource.
Consider the following request:
OPTIONS http://packtservice.com/Authors/1 HTTP/1.1 HOST: packtservice
If the request is authorized and authenticated, it might return something like the following:
200 OK Allow: HEAD, GET, PUT
The response is actually saying that the service can be called using only all these methods.
Make sure you use the HTTP methods according to their specification. If you design the service to allow GET
, but perform a delete operation inside that, then clients will get confused. As they try to GET
something, it will actually delete the resource, which is weird.
The following is a request that is made with GET
, but it actually deletes the resource inside the server (just imagine):
GET http://packtservice.com/DeleteAuthor/1 HTTP/1.1 HOST: packtservice
The preceding request might work and delete the resource, but this is not regarded as a RESTful design. The recommended operation would be to use DELETE
method to delete a resource like the following:
DELETE http://packtservice.com/Authors/1 HTTP/1.1 HOST: packtservice
POST versus PUT explained
The use of POST
and PUT
can be summarized in the following two points:
PUT
is idempotent—it can be repeated, and yields the same result every time. If the resource does not exist, it will create it; otherwise, it will update it.POST
is nonidempotent—multiple resources will be created if it is called more than once.
The preceding contrast between these verbs is just a general difference. However, there is a very important and significant difference. When using PUT
, specifying the complete URI of the resource is necessary. Otherwise, it won't work. For example, the following won't work as it does not specify the exact URI of the author, which can be done by specifying an ID:
PUT http://packtservice.com/Authors/
To fix this, you can send an ID with this URI using something like the following:
PUT http://packtservice.com/Authors/19 created/updated.
This means that the author with the ID 19
will be processed, but if that does not exist, it will be created first. Subsequent requests with this URI will be considered as requests to modify the author resource with an ID of 19
.
On the other hand, if we do the same with a POST
request like the following, it will create a new author resource with the posted data:
POST http://packtservice.com/Authors/
Interestingly, if you repeat this, you will be responsible for duplicate records with the same data. That is why it is nonidempotent in nature.
Note the following request with POST
with an ID. Unlike PUT
, POST
won't consider this for a new resource, if that is does not exist. It will always be treated as an update request:
POST http://packtservice.com/Authors/19 updated.
The following are the main points to focus on in this section:
PUT
creates or updates one resource, as long as you are calling the same URIPUT
andPOST
behave the same, if the resource already existsPOST
, without an ID, will create a resource each time it is fired
Layered system
Most modern applications are designed using multiple layers, and the same is expected from a RESTful service. In a layered system, each layer is restricted to only seeing or knowing the next layer in the hierarchy.
Having a layered architecture helps improve the code's readability, hides complexities, and improves the code's maintainability. Imagine that you have one layer and everything takes place in it, from authentication to database operations. This is absolutely not recommended, as the primary components, such as authentications, business logic, and database operations, are not separated out.
Thus, this constraint is expected from a RESTful service, and no client can actually say that it is connected to the final layer.
Advantages and disadvantages of RESTful services
The following are some advantages and disadvantages of RESTful services:
Advantages
The advantages of using RESTful services are as follows:
- No dependency on a platform or any programming language
- Standardized methods through HTTP
- It doesn't store the state of the clients on the server
- Supports caching
- Accessible to any type of client, such as mobile, web, or desktop
Disadvantages
While there are advantages, there must be some cons. Let's look at some disadvantages of RESTful services:
- If the standards are not followed correctly, they are difficult for clients to understand
- Documentation becomes problematic as no such metadata is provided
- Security is a concern, if no such process is followed to restrict the access of resources