In this post we will talk about elements of RESTful architecture. However before we do that I would recommend reading the previous part of the series
In REST, the various software components that interact together are known as software components. These could be considered as units working together in a RESTful design. These components are organized by the role they perform in the system. Dr. Fielding has defined 4 major component types in his dissertation.
Origin Server – is the component that listens for requests and provides responses. These responses could also be representation of resources as well. The origin server own the url namespaces for all its resources.
Examples of origin server include IIS, Apache, etc.
User Agent – is responsible for initiating a request or a state transition for a resource.
The most common example of a user agent are web browsers.
Gateway – sits between the origin server and user agent and provides additional processing like caching, load balancing, etc. Gateway represents multiple origin servers to the network. There can be multiple gateways on the network between the origin and user agent.
Examples of gateway are Synapse, Squid, etc.
Proxy – sits between the origin server and user agent and provides additional processing like caching, load balancing, etc. A proxy represents multiple user agents on the network and the client could determine whether to use or not to use proxy.
Examples of proxy are CERN Proxy, Netscape Proxy, etc.
Connectors could be thought of as interfaces implemented by components to work. Connectors are organized by the role they play for the component. A component can implement multiple connectorsThe various types of connectors are:
Server – is the connector that listens for requests and provides responses. These responses could also be representation of resources as well. The origin server own the url namespaces for all its resources.
Examples of server include Web Server API, etc.
Client – is the connector that starts the resource request or resource state transformation requests.
Examples of client connector include Http library, etc.
Cache – connector manages the storage of resources and states of resources which could be used for specified time. This could be located at client or server and reduces lag time for requests.
Examples of cache include Browser cache, etc.
Resolver – transforms the resource identifiers into whatever is the address format (ip address, hostname, etc) so that the 2 components could make a connection. The advantage of using a resolver is that is provides deviousness between components to a level. This increases the lifetime of component references with changes in network topology, etc.
Examples of resolver include bind DNS lookup, etc.
Tunnel – connector relays request across a boundary. Any component could switch from active behavior to tunnel behavior.
Examples of tunnel SOCKS, SSL after HTTP CONECT, etc.
Resources are concepts and ideally should never change. These resource maps to entities and these entities or mapping could change overtime.
Examples of resources are video on YouTube, image on flicker, wall on Facebook, etc.
We could understand it with a simple example. We have resources or concepts like Employee, Manager, Developer and Trainee as show in the image below. We should remember that these concepts could still exist even when they do not have any actual entities mapped to them.
Let us introduce 2 entities: John is a manager in the company and Steve is a trainee. This will introduce a mapping between the concepts and entities John and Steve. Also John and Steve have a conceptual identities of their own as well. It would look like below. John is an employee as well as a manager.
Now say after few months the company decides to hire the intern (Steve) and designate him as developer. The concepts will remain the same but this will change the mapping of the concepts with entities. The employee resource now points to 2 different entities. Also let’s assume that the company gets another intern named Nick. While the concept of intern has not changed but still the mapping of resource to entity is now with Nick instead of Steve.
So the key point to note here is that resource is a concept in the system and it should be a stable concept. However what could change overtime is the mapping of these concepts with entities that forms the value for the resources. It is a common mistake to design the resources as entities but a costly one.
Since resource is a unique concept in a system then it is only logical to have a unique resource identifier for a resource. The server uses the resource identifier to make the resource available. As we discussed in the previous section that the resource should be stable concept which also implies that the resource identifier should not change frequently however the mappings that provide the value might change.
Now when I am designing a RESTful system for working over http then we will need resource identifiers for all the resources we saw in the previous section and they will look something like below. We have urls identifying resources. We have created hierarchy with employee at the top followed by the manager, developer, intern as well as each employee.
Along with the application data the resources also include the information specific that describes the resource itself. Metadata provides additional information such as url, links, location information, alternate resource identifiers for different formats or entity tag information about the resource itself. In case of HTTP this information is available in the headers. For example in the image below we could see the ETag information which is the metadata.
A representation is a concrete counterpart of the resource (concept) as it represents that concept at a point in time. There can be any number of representations for any given resource. In the modern web environment the same resource might be in different representations for serving different types of user agents. A representation is nothing more than a sequence of bytes.
Content negotiation is a process of selecting the best representation of a resource. The two categories of content negotiation are
Server driven content negotiation – In this type of content negotiation the server decides the representation of the resource depending upon the information available in client request.
Agent driven content negotiation – In this type of content negotiation the server and the agent work together to determine the best representation. Generally the server provides the user agent with multiple choices as links to those representations and then the agent chooses one of those representations.
In the Http request we could specify the type of content we are expecting.
Just like the resource metadata it also describes the representation and in case of HTTP this information is available as part of the HTTP Headers. It helps the clients and server to determine the course of action of the byte sequence (representation).
We could see in the image below that in the Request Headers are accepting contents of type text/html, application/xml, etc. and hence we have received the content of one of those types (application/xml).
This defines the purpose of a message between components, such as the action being requested. Control data exists for both request and responses in Http.
Example of control data are If-Modified-Since, If-Match, If-None-Match
Hypermedia is all about reducing the coupling between a client and a server. This decoupling specifically refers to the client not knowing all the urls that are exposed a service. So ideally a client should be aware of only the entry point url of the service and then should be able to dereference all the other links of the service based on requirement.