Introduction to the Basics of RESTful Architecture
A web service is a software service or a software functionality provided by one set of computing devices to another set of computing devices. These devices communicate using established or standardized communication protocols through the World Wide Web (WWW).
This chapter intends to refresh your understanding of a few fundamental concepts of the web and its architecture, and the way it is evolving, hoping to lay a firm foundation for RESTful service designs and applications. The following topics are covered in this chapter:
- A brief history of the WWW and its evolution
- WWW layers and architecture
- Web API development models and REST-based service communication
- A brief introduction to service-oriented architecture
- Resource-oriented architecture principles and characteristics
- Introduction to REST
- REST constraints
- RESTful qualifiers
- REST architecture goals
Technical requirements
As this book deals with intermediate to advanced topics of RESTful design patterns, we expect you to have a good understanding of web service concepts and their unique functions. As mentioned earlier, this chapter is an attempt to refresh your understanding of various fundamental concepts of the WWW, its evolution, and the types of web services it offers, so there are no formal technical requirements for this chapter.
Evolution of web technologies
Generally, the aim of this book is to provide more elaborate RESTful patterns; however, this section intends to give you a quick introduction to web services and their evolution since the early 1990s, giving you exciting facts about Web 1.0 through to Web 3.0, and then moving on to details about service-oriented architecture (SOA) and resource-oriented architecture (ROA).
As you are aware, today's web is a universe in itself, with a massive amount of interlinked web-based apps, images, videos, photos, and various interactive content. Which web technologies have made this possible, where did it start, how has it evolved over time, and how does it enable web app developers to develop amazing and interactive web experiences?
The following diagram provides a brief overview of the WWW and its evolution over time. Please note that each web version has its enabling technologies mentioned in the corresponding box:
Let's discuss Web 3.0 more and focus on web services and their evolution as part of the third generation.
Learning about Web 3.0
The following sections focus on Web 3.0 and the evolution and history of web services.
Web 3.0 is generally referred to as executing semantic web, or read-write-execute web. Web 3.0 decentralizes services such as search, social media, and chat applications that are dependent on a single organization to function. Semantic and web services are the primary constituents of Web 3.0.
The following diagram depicts layers of typical Web 3.0 constructs. The semantic web layers are Static Web, Translations, and Rich Internet Applications (RIA) or Rich Web built on top of the internet:
This data-driven web adjusts according to the user's searches, for instance, if a user searches for architecture patterns, the advertisements shown are more relevant to architecture and patterns; it even remembers your last search and combines the last searched queries as well. Interesting isn't it?
What you see in the following diagram is a Web 3.0 stack, with various building blocks as URI, Unicode representations, syntax (XML/JSON), RDFS taxonomies, and so on; they constitute a Web 3.0 stack:
Let's move on to the web service architecture, the specifications, and the communication protocols, as they are the fundamentals before we move to ROA, SOA, and Representational State Transfer (REST) or RESTful services.
Learning about web service architecture
Web services are a method of communication between two computing devices over a network, and the communication happens in standardized ways (and specifications) for the integration of heterogeneous web applications using XML/JSON, SOAP, WSDL, and UDDI. XML/JSON is the data format that provides metadata for the data that it contains; SOAP is used to transfer data; WSDL is used for defining available services to be consumed, and UDDI will have the list of services available.
Web services architecture (WSA) mandates the presence of certain characteristics, and suggests a few optional ones, when developing any web service.
WSA consists of three significant roles, as you can see in the following diagram, and they are as follow:
- Service Provider
- Service Consumer
- Service Broker
This is shown in the following diagram:
The Service Requestor finds the Service Provider through UDDI, and contacts the provider using the Simple Object Access Protocol (SOAP). The Service Provider then validates the service request and responds to the requestor with XML/JSON as a service response.
Discussing the web API
So far, we have discussed the fundamentals of the client-server/web services paradigm, and the way they communicate with standard protocols; however, we are yet to touch upon REST-based communication and after all, that's what this book is about. This section will cover the introduction of web APIs, and how a web API is a development model for web services. The communication between the devices is REST-based. RESTful APIs do not use/require XML- based web service protocols, such as SOAP or WSDL, to support their interfaces, but they use simplified representations instead.
The following diagram depicts the web API and their simplified representations as the client side and the server side are exposed to each other through high-level interfaces:
So the web API, as shown in the preceding diagram, is available on both the client side and the server side. The client-side interfaces are generally exposed as JavaScript or browser plugins, and the server-side interfaces are generally exposed through the web as JSON/XML. Some of the key terminologies that we will come across concerning web APIs are endpoint, uniform resource identifier (URI), and resources.
The web API is an application programming interface (API) for either a web server or for a web browser. So, Web API is a concept or methodology for accessing any API (available over the web) through the HTTP protocol. There are many categories of APIs, SOAP, XML-RPC, JSON-RPC, REST, and so on. APIs can be developed with any programming language such as Java, .NET, and many more.
So now you have got an idea of what is a Web API is and where REST API development fits into the Web API landscape, let's move on and see more details of SOA, ROA, REST, RESTful APIs, and their key constituents in the following sections.
Learning about service-oriented architecture
Service-oriented architecture is an architectural style of web services. It defines some standards and lays down best approaches to design and develop a web service. Any web service is the logical representation of repeatable business activities that have a specified outcome, such as retrieving a weather report for a particular city, accessing stock prices for a given stock, updating a record to an inventory service, and so on. SOA is self-contained, and also provides guidelines to combine a service with other services as well. Another fact about SOA is that it is a black box (or abstract) to the service consumer who consumes it.
In short, SOA is essentially a collection of services, those services communicate with each other, and a service is an operation or a function that is well defined, self-contained, and independent of other service contexts and states. Services are applications hosted on application servers and interact with other applications through interfaces.
Learning about resource-oriented architecture
Resource-oriented architecture is a foundation of the semantic web (please refer to the Web 3.0 section of this chapter). The idea of ROA is to use basic, well-understood, and well-known web technologies (HTTP, URI, and XML) along with the core design principles.
As we all know, the primary focus of web services is to connect information systems, and ROA defines a structural design or set of guidelines to support and implement interactions within any connected resources. Any business entity can be represented as a resource, and it can be made accessible through a URI.
For example, in an organization's human resource system, each employee is an entity, and salary, employee details, and profiles are associations (descriptors) of that entity.
The following is a quick comparison table for object-oriented and resource-oriented concepts, and it gives a quick insight as to what ROA is:
Objects in object-oriented architecture |
Resources in ROA |
Every entity is defined as an object |
Entities are services |
An object has attributes and actions |
A service has descriptions and contracts |
Objects need to maintain state to interact |
Interacts over the network with a defined location or address |
Resource-oriented design
The resource-oriented design section intends to walk you through the ROA design guidelines, design principles, and characteristics, along with its properties as well. Having introduced ROA properties, we will look at REST architecture in subsequent sections.
ROA-based web services describe a self-discoverable entity, and modeling is based on its logical form (unlike services, as they are based on the technical form).
Let's look at the basic blocks of ROA such as resources, representations, and so on in the following diagram:
The blocks in the preceding diagram represent the typical structure of ROA and give an idea of how resources are consumed by the service consumers.
Let's briefly consider the concepts and properties of ROA, as follows:
- Resource providers: Resource providers expose the resources for the service consumers to invoke the services with HTTP methods. Microsoft Azure and Amazon AWS are simple examples of resource providers.
- Resource: A resource is an explicit reference to an entity that can be identified and assigned and, most importantly, referenced as a resource. Some examples of resources could be servers, devices, web pages, JavaScript, or the latest version of software, the latest defect in software, a directory or list of information about an organization, and so on.
- Resource name: The resource name is the unique name or identification for the resource. So, no two resources can point to the same data. For instance, the latest version of software is 2.0.9.
- Resource representation: Resource representation is the useful information about the current state of a resource, specified with a specific format, in a specific language.
- Resource link and connectedness: Represents (linkage) another resource or the resource itself. Connectedness is all about how reliable and relevant the resource's links are.
- Resource interface: The resource interface is an interface for accessing the resource and handling its state.
- Addressability: Addressability is exposing datasets or functionalities as a resource, and the addressability of a resource happens through URIs.
- Statelessness: Statelessness is maintaining the isolation and independence of client and server states. Every request from the client should be self-contained.
- The uniform interface: Every service needs to use the HTTP interface the same way, such as GET, POST, PUT, DELETE, and so on. The uniform interface simply means using some common nomenclature that is interpreted the same way across the web. For example, GET does mean get (read) something.
The following table summarizes the HTTP operations that can be used to implement an ROA-based web service:
HTTP operation |
Description |
GET |
Read the resource representations |
PUT |
Create a new resource |
DELETE |
Delete the resource (optionally linked resource as well) |
POST |
Modify the resource |
HEAD |
Meta information of the resource |
The preceding table shows the HTTP methods to implement ROA.
The benefits of ROA
The following are the benefits of ROA:
- Independent of client contracts: Free from interface agreements/contract formulations, that is, no need to formulate the contact as the entire web is based on HTTP operations.
- Explicit state: As the resource itself represents states, servers won't receive unknown application specific payloads; the server does not have to keep track of the client who called the server, and also the client doesn't need to know which server it has talked to.
- Scalability and performance: Scalability with ROA is shown by characteristics such as no contract boundaries, explicit states, and freeing up the clients from the server's stickiness(session). The performance improvement regarding response time for the ROA caching, load-balancing, indexing, and searching play a significant role in improving performance.
A contract or agreement is fundamentally a collection of metadata that defines many aspects of an underlying software program.
Beginning with REST
So far, we have looked at ROA and a set of guidelines, such as statelessness, resources, addressability, uniform resources, and so on. Those guidelines are the fundamental implementation of REST architecture. As this book is all about RESTful patterns, we are going to explore more about the REST architectural style in this section.
The REST concepts were submitted as a PhD dissertation by Roy Fielding. The fundamental principle of REST is to use the HTTP protocol for data communication (between distributed hypermedia systems), and it revolves around the concept of resources where each and every component considered as a resource, and those resources are accessed by the common interfaces using HTTP methods:
The preceding diagram shows you where REST stands in the ROA architecture and how it can be accessed by different consumers.
REST is an architectural style and not a programming language or technology. It provides guidelines for distributed systems to communicate directly using the existing principles and protocols of the web to create web services and APIs, without the need for SOAP or any other sophisticated protocols.
The REST architecture is simple and provides access to resources so that the REST client accesses and renders the resources on the client side. In REST style,URI or Global IDs helps to identify each resource. As you know REST uses several resources representations to represent its type such as XML, JSON, Text, images and so on.
REST architecture style constraints
There are design rules that are applied to establish the different characteristics of the REST architectural style, which are referred to as REST constraints:
The preceding diagram depicts REST constraints in a typical web/internet-based application. The following are the REST constraints:
- Client-server
- Statelessness
- Cacheable
- Uniform interface
- Layered systems
- Code on demand
Beginning with client-server
The client-server architecture or model helps in the separation of concerns between the user interface and data storage:
Let's discuss the client and server in the context of ROA as follows:
- Client: It is the component that is the requestor of a service and sends requests for various types of services to the server
- Server: It is the component that is the service provider and continuously provides services to the client as per the requests
Clients and servers typically comprise distributed systems that communicate over a network.
The client in client-server architecture
There is no upper bound on the number of clients that can be serviced by a single server. It is also not mandatory that the client and server should reside in separate systems. Both client and server can reside in the same system, based on the hardware configuration of the system and the type of functionality or service provided by the server. The communication between client and server happens through the exchange of messages using a request-response pattern. The client basically sends a request for a service, and the server returns a response. This request-response pattern of communication is an excellent example of inter-process communication. For this communication to happen efficiently, it is necessary to have a well-defined communication protocol that lays down the rules of communication, such as the format of request messages, response messages, error handling, and so on. All communication protocols that are used for client-server communication work in the application layer of the protocol stack. To further streamline the process of client-server communication, the server sometimes implements a specific API that can be used by the client for accessing any specific service from the server.
The service in client-server architecture
The term service used in the context of client-server architecture refers to the abstraction of a resource. The resource could be of any type and based on the one provided by the server (service); the server is named accordingly. For example, if the server provides web pages, it is called a web server, and if the server provides files, it is called a file server, and so on. A server can receive requests from any number of clients at a specific point in time. But any server will have its own limitations about its processing capabilities. Often, it becomes necessary for a server to prioritize the incoming requests and service them as per their priority. The scheduling system present in the server helps the server with the assignment of priorities.
Client-server benefits are in addition to separation of concerns and help with the following:
- Improving the portability of the user interface
- Improving scalability by simplifying server implementations
- Developing with standalone, independent testable components
Understanding statelessness
The statelessness constraint helps services to be more scalable and reliable. Statelessness, in the REST context, means that all the client requests to the server carry all the information as explicit (stated), so that the server understands the requests, treats them as independent, and those client requests keep the server independent of any stored contexts. Keeping the session state within the client is important to manage this constraint in the services.
The following diagram shows the Service Consumer (client) and the Service States are independent and managed within the client and server respectively:
The statelessness constraint imposes significant restrictions on the kind of communications allowed between services and consumers, to achieves its design goals. The following are the restrictions to achieve statelessness:
- It is the complete responsibility of the client to store and handle all the application states and the related information on the client side.
- The client is responsible for sending any state information to the server whenever it's needed.
- No session stickiness or session affinity on the server for the calling request (client).
- The server also needs to include any necessary information that the client may need to create a state on its side.
- HTTP interactions involve two kinds of states, application state and resource state, and statelessness applies to both. Let's see how the statelessness constraint is handled in each state:
- Application state: The data that is stored on the server side and helps to identify the incoming client request, using the previous interaction details with current context information
- Resource state: This is referred to as a resource representation, and it is independent of the client (the client doesn't need to know this state unless it is available as response is needed), and this is the current state of the server at any given point in time
Advantages and disadvantages of statelessness
The following are some advantages of statelessness:
- As the server does not need to manage any session, deploying the services to any number of servers is possible, and so scalability will never be a problem
- No states equals less complexity; no session (state) synchronize logic to handle at the server side
- As the service calls (requests) can be cached by the underlying application, the statelessness constraint brings down the server's response time, that is, it improves performance with regard to response time
- Seamless integration/implementation with HTTP protocols is possible as HTTP is itself a stateless protocol
- Improves visibility as each request is its own resource and can be treated as an independent request
- Improves reliability as it can recover from partial failures
The following are some disadvantages of statelessness:
- Increase per-interaction overhead
- Each request of webservices needs to get additional information so that it get parsed (interpreted) so that the server understands the client state from the incoming request and takes care of the client / server sessions if needed
Caching constraint in REST
Caching is the ability to store frequently accessed data (a response in this context) to serve the client requests, and never having to generate the same response more than once until it needs to be. Well-managed caching eliminates partial or complete client-server interactions and still serves the client with the expected response. Obviously, caching brings scalability and also performance benefits with faster response times and reduced server load.
As you can see in the next diagram, the service consumer (Client) receives the response from the cache and not from the server itself, and a few other responses are directly from the server as well. So, caching helps with the partial or complete elimination of some interactions between the service consumers and so helps to improve efficiency and performance (reduced latency time in response):
There are different caching strategies or mechanisms available, such as browser caches, proxy caches, and gateway caches (reverse-proxy), and there are several ways that we can control the cache behavior, such as through pragma, expiration tags, and so on. The following table gives a glimpse of the various cache control headers one use to can fine-tune cache behaviors:
Headers |
Description |
Samples |
Expires |
Header attribute to represent date/time after which the response is considered stale |
Expires: Fri, 12 Jan 2018 18:00:09 GMT |
Cache-control |
A header that defines various directives (for both requests and responses) that are followed by caching mechanisms |
Max age=4500, cache-extension |
E-Tag |
Unique identifier for server resource states |
ETag:uqv2309u324klm |
Last-modified |
Response header helps to identify the time the response was generated |
Last-modified: Fri, 12 Jan 2018 18:00:09 GMT |
For more about cache-control directives. Please refer to https://tools.ietf.org/html/rfc2616#section-14.9.
Benefits of caching
Obviously, there are a lot of benefits to caching frequently accessed data, and the following are the significant ones:
- Reduced bandwidth
- Reduced latency (faster response time)
- Reduced load on the server
- Hide network failures and serve a client with the response
The cache constraint builds upon the client-server and stateless ones, with the requirement that responses are implicitly or explicitly labeled as cacheable or non-cacheable.
Understanding the uniform interface
As we mentioned earlier in the uniform interface section as part of ROA, REST-based services can use the HTTP interface, such as GET, POST, PUT, DELETE, and so on, to maintain uniformity across the web. The intention of a uniform interface is to retain some common vocabulary across the internet. For example, GET does mean to get (read) something from the server. The services can independently evolve as their interfaces simplify and decouple the architecture, and the uniform interface brings a uniform vocabulary to those resources as well. The following diagram depicts the combination of HTTP Methods and the Resource Names for Uniform Interfaces:
There are four guiding principles suggested by Fielding that constitute the necessary constraints to satisfy the uniform interface, and they are as follows:
- Identification of resources
- Manipulation of resources
- Self-descriptive messages
- Hypermedia as the engine of application state
We will see each constraint in detail in the following sections.
Identification of resources
As we have seen in earlier sections, a resource represents a named entity in a web application, and it is usually a Uniform Resource Locator (URL). So, an entity can be identified and assigned as a resource by an explicit reference to it.
A URL in a web application is usually a link, and it is in fact a URI. For example, a home page URI, https://developer.twitter.com, uniquely identifies the concept of a specific website's root resource. In REST constraints, the URIs we use are described as follows:
- The semantics of the mapping of the URI to a resource must not change. For instance, Twitter's https://api.twitter.com/1.1/statuses/retweets/:id.json as a URI may never change, and of course the contents or values will keep improving, according to the latest updates.
- Resource identification is independent of its values so two resources could point to the same data at some point, but they are not the same resource.
- For example, URI 1, https://api.twitter.com/1.1/statuses/retweets/:id.json, returns a collection up to 100 of the most recent retweets of a tweet (specified by the ID).
- The other URI 2, https://api.twitter.com/1.1/statuses/retweeters/ids.json, responds with a collection of 100 user IDs (maximum) belonging to users who have retweeted the tweet (specified by the ID parameter).
- URIs bring benefits such as only one way to access a resource, dynamic media types for resource responses (serve the media type at the time it is requested) with the help of the Accept headers, and clients accessing those dynamic resources do not need to change any identifiers if any change is made in the response content type.
Manipulation of resources
Resources, once identified, can be returned by the server in a different format, such as JSON, XML, HTML, PNG, SVG, and so on. These formats are a representation of the identified resources, and the client will understand the list of possible well-defined formats or media types (also called Multipurpose Internet Mail Extension (MIME)) from the headers.
The resource's representation is manipulated or processed by clients. The application needs to support more than one representation of the same resource and the same URI; in other words, the same exact resource is represented by different clients in different ways.
Let's take an example; a document might be represented as JSON to an automated program, but as HTML to a web browser. The purpose of these representations is to provide a way to interact with the resource, and so the clients can indicate the intended representations they wish to receive.
The preceding conceptual distinction allows the resource to be represented in different ways without changing its identifiers. It is possible with the HTTP header (Accept) getting passed to the server by the clients in each request. The resources are updated or added by sending representations from the client by the RESTful application. The following diagram is a sample representation format, captured for a sample request from my Postman tool:
So, the decoupling of the resource's representation from the URI is one of the crucial aspects of REST.
The following list shows various content-type representation formats (as headers) that one can use in the request or response:
- Text/HTML, text/CSS, text/JavaScript
- Application/XML, application/JSON, application/x-www-form-urlencoded
- Image (SVG, JPG, PNG, and so on)
Self-descriptive messages
A client's request and server's response are messages; those messages should be stateless and self-descriptive. They can have a body and metadata. RESTful applications operate on the notion of constrained message types (GET, HEAD, OPTIONS, PUT, POST, and DELETE) and they are fully understood by both the server and the client.
A resource's desired state can be represented within a client's request message. A resource's current state may be embodied within the response message that comes back from a server. As an example, a wiki page editor client may use a request message to transfer a representation that suggests a page update (new state) for a server-managed web page (resource). It is up to the server to accept or deny the client's request.
Self-descriptive messages may include metadata to convey additional details regarding the resource state, the representation format and size, and even the message itself. An HTTP message provides headers for organizing the various types of metadata into uniform fields. The following diagram depicts a sample request and its headers, and the server response for the same request along with its headers:
So a self-descriptive message in REST style is all about not maintaining state between client and server, and needs to carry enough information about itself or explain with explicit states. So in the following table, you can see the self-descriptive messages with examples:
Resource |
GET |
PUT |
POST |
DELETE |
|
Get all resources belonging to the collection |
Replace with another collection |
Create the collection |
Delete the whole collection |
|
Lookup for title 18 |
Modify title 18 |
Create new resource as title 18 |
Delete title 18 |
Hypermedia as the Engine of Application State
Hypermedia as the Engine of Application State (HATEOAS) is one of the most critical constraints; without addressing it, services cannot be termed RESTful services. However, before we get into the details of HATEOAS, let's get a brief idea about the Richardson Maturity Model (RMM) as it is an essential reference and serves as a guide to any RESTful services to follow the HATEOAS constraints.
The RMM is a model developed by Leonard Richardson, and it breaks down the principal elements of the REST approach to Resources, HTTP Verbs, and Hypermedia Controls. The following diagram depicts the RMM's four levels, and those levels are used to grade the APIs; that is, the better the API adheres to these constraints, the higher the scores are:
So, an API is fully qualified to be a RESTful API only when it scores Level-3. We will see more guidelines for how APIs can be RESTful APIs later in this chapter. However, now you know why we touched on the RMM here before we move on to HATEOAS.
Once the client gets the initial response to its resource request from the server, it should be able to move to the next application state by picking up hyperlinks from the same received response.
Let's take an example to explain the preceding statement. Say a client will POST a representation of a new TODO item to the server, then the state of the Task Manager application will change by growing the list of the TODO item and both POST and GET are accomplished via hypermedia links.
Resource representations are shared by sending self-descriptive messages to any identified resources. Then, they change the state of the application, and the client with the received hypermedia links will move to the next application state.
In an HTML browser, GET methods are accomplished by clicking on anchor tags (<a>) that have an HREF attribute, and HREF contains a resource URI. POST methods are achieved by pressing the Submit button within a <form> tag that has an action URI attribute. The anchor (<a>) and form (<form>) tag elements were sent to the client as part of the representation of the client requested resource.
The web contracts (sharing representations) are expressed regarding media types; a client that calls the service would know the media types and how to process the content as well. So the application enables the server to inform the client of possible ways to change its application state via hypermedia.
Some media types work well (in harmony) with the web, and they are called hypermedia formats. The formats that host URIs and links are hypermedia formats.
The following diagram depicts a sample JSON response from a server without and then With HATEOAS (with links and HREFs):
Before we conclude this section, let's have a recap of HATEOAS:
- HATEOAS means an application state representation (resource) that includes links to related resources. The absence or presence of a link on a page is an essential part of the resource's current state and so is essential for the RESTful APIs.
- A URI is a differentiator of REST architectural style, and defining the URIs is really critical, as it will be around for a very long time. So it is crucial to evaluate the links (when they change), keeping their future in mind, or put it in a simpler way, the URI should stay the same regardless of the many changes its representations go through. There is an interesting read about this at https://www.w3.org/Provider/Style/URI.html.en; it supports this point in great detail, and we encourage you to have a look.
Layered systems
In general, a layered system consists of layers with different units of functionality. The essential characteristics of layered systems are that a Layer communicates by means of pre-defined interfaces and communicate only with the layer above or layer below, and the layers above rely on the layers below to it to perform its functions. Layers can be added, removed, modified, or reordered as the architecture evolves. Consider the following diagram of layers:
So, let's start with an example. The REST style allows services to make use of a layered system architecture where we deploy the REST APIs on server A, store data on server B, and authenticate with server C. The client calling the REST API doesn't have any knowledge of the servers the services use:
The REST architectural style suggests services can consist of multiple architectural layers. The layers will have published service contracts or intermediaries. The logic within a given layer cannot have knowledge beyond the immediate layers above or below it within the solution hierarchy.
The intermediaries have the following properties:
- Intermediaries can be event-driven middleware components to establish processing layers between consumers and services
- They can be proxies (selected by the client to provide interfaces with data translation services, enhanced performance, or security protections)
- They can be gateways as well (chosen by the server or the network, and used for data translation, security enforcement, and performance enhancements)
A client may not be able to tell whether it is connected to the services directly with the server endpoint, or to an intermediary before reaching the actual server. Intermediary servers help to attain improved system scalability by having load balancers and shared caches. Layers may also enforce security policies for their calling clients.
It would be helpful for us to understand a few applications of layered systems (design), so let's look at the following points:
- Enables the service clients to invoke the services; the service that is called by the client doesn't reveal any information about other services it's using to process the client requests. In other words, the service consumer (client) only knows about the service it directly calls and doesn't know about other services consumed by the called service to process its requests.
- The messages between the client and the server are processed by intermediaries helping to free the clients from the runtime message processing logic and making them unaware of how those messages are processed in other layers as well.
- It's very critical for stability and scalability to add or remove layers in the layered system without any changes to the service consumers.
- Request and response messages won't divulge any details to the recipients about which layer the message comes from.
While layered systems bring additional latency and overhead as a drawback, there are trade-offs that are the benefits of layers and layered system designs, as follows:
- Encapsulates legacy services
- Introduces intermediaries
- Limits system complexity
- Improves scalability
Code on demand
In distributed computing, code on demand (COD) is any technology that enables the server to send the software code to the clients to be executed on the client computer upon request from the client's software. Some well-known examples of the COD paradigm on the web are Java applets, the Adobe ActionScript language for the Flash player, and JavaScript.
The following can also be called the advantages of COD:
- COD is the optional constraint of REST and intends to allow business logic within the client web browser, applets, JavaScript, and ActionScript (Flash). I think video on demand sites are good examples of COD, as the video data files are downloaded and played according to the client system's specifications.
- Only one optional constraint according to REST architectural style and it is COD. COD allow it clients to be flexible because the server that decides how specific items need to be handled on the client side. For instance, with COD, a client may download action scripts such as JavaScript, Applets (not widely used these days), Flex scripts to encrypt the client-server communication, so the underlying servers won’t aware of any specific encryption methods used in the process.
- COD can also be applied to services and service consumers. For instance, service design can enable the servers to dynamically defer some portions of logic to the service client programs. This approach of delaying code execution to the client side is justifiable when service logic can be executed by the consumer more efficiently or effectively.
- RESTful applications may very well be able to utilize clients that support COD. For instance, web browsers can allow servers to return scripts or links that can be executed at the client side. This sort of additional code execution helps to expand the capabilities of the client, without needing the user to install new client software.
- In the COD style, a client component has access to a set of resources, but not the know-how of how to process them. It sends a request to a remote server for the code representing that know-how, receives that code, and executes it locally.
However, the down side of using COD is reduces the visibility of the underlying API, and not every API prefers these kind of flexibility.
RESTful service mandates
In one of the online discussion forums, Roy Fielding recorded his frustration about a service that claims to be RESTful, but that service is a mere HTTP-based interface. The service was not fulfilling all the necessary REST architecture constraints. He even said that if the Engine of Application State (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API.
With that said, any services that need to be termed RESTful must strictly adhere to the mandatory REST architecture constraints. Those constraints are design rules that are applied to establish the distinct characteristics of the REST architectural style.
Roy, the founder of the REST style, enforces the following REST constraints as mandatory for any web service to be qualified as RESTful. These mandatory constraints are as follows:
- Client-server
- Statelessness
- Cache
- Interface/uniform contract
- Layered system
- The optional REST constraint is COD (architectures that do not use this feature can still be considered RESTful)
Each constraint is a predetermined design decision and will have positive and negative influences on the services. However, these constraints are meant to provide a better architecture that resembles the web (perhaps positive impacts balanced with negative consequences).
There may be a need for potential trade-offs when deviating from REST constraints. Ensure those trade-offs don't weaken or eliminate the mandated constraints. If so, that architecture may no longer conform to REST, or in other words, the services (architecture) are not RESTful.
Architectural goals of REST
The REST architectural style brings a set of properties that help to establish the design goals that are embedded in the application of REST constraints. These properties are as follows:
- Performance
- Scalability
- Simplicity
- Modifiability
- Visibility
- Portability
- Reliability
- Testability
The preceding properties signify a target state of software architecture and fundamental qualities of the WWW. Adhering to REST constraints in design decisions helps to achieve the preceding listed goals, and, of course, these properties can be further improved with more design decisions that are not necessarily parts of REST. However, as quoted in the RESTful services mandate section, a web service, to be called a RESTful service, should adhere to the RESTful constraints.
Summary
Let's summarize what we have covered in this chapter and what we can take away in the context of the REST architectural style. We started with a brief history of the evolution of the World Wide Web, its layers, and its architecture. Then we moved on to the web API, a development model for web services, and how REST-based services communicate with existing web protocols with simplified representations.
We looked briefly at SOA and also in more detail at ROA. We covered the purpose of ROA (to use simplified, well-understood and well-known web technologies along with core design principles), its principles, and its characteristics as well. After setting the ground with ROA, we got introduced to the concept of REST; the mandatory constraints of REST architecture, such as client-server, statelessness, cacheable, uniform interface, and layered systems; and also the optional code on demand constraints.
As part of a uniform interface, we learned its four guiding principles, which are the identification of resources, manipulation of resources, self-descriptive messages, and HATEOAS, and we also touched upon the importance of the RMM to get a foundation for building RESTful services.
This chapter described in detail the five mandatory constraints and how in Roy's view they define an architectural style as RESTful. It is critical to understand what makes REST RESTful and what does not.
We concluded this chapter with a quick introduction to the software architecture properties of the WWW, and how REST constraints help to achieve the architecture goals of REST, such as performance, scalability, and simplicity.
I hope you have enjoyed this chapter. In the next chapter, we will learn about API design strategies, such as self-service enablement, resource collaboration, and how to address security and scalability concerns along with RESTful API guidelines and constituents.