Representational state transfer (REST) is a software architectural style consisting of a coordinated set of architectural constraints applied to components, connectors, and data elements, within a distributed hypermedia system. REST ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements.
The term representational state transfer was introduced and defined in 2000 by Roy Fielding in his doctoral dissertation at UC Irvine. REST has been applied to describe desired web architecture, to identify existing problems, to compare alternative solutions, and to ensure that protocol extensions would not violate the core constraints that make the web successful. Fielding used REST to design HTTP 1.1 and Uniform Resource Identifiers (URI). The REST architectural style is also applied to the development of web services as an alternative to other distributed-computing specifications such as SOAP.
REST Business Drivers
- Network based api instead of library based api
- Rise of devices (smartphones, tablets, etc)
- It is critical to build a scalable architecture i order to take advantage of a scalable infrastructure
Properties of REST
- Heterogeny: ability to interoperate with other participants regardless of language or platform
- Evolvability: client and servers can evolve separately
What REST is not
- not a way to call methods over a network without the overhead of SOAP and WSDL
- an architecture built on top of HTTP is not inherently RESTful
- Yet most RESTful services in use today are built on top of HTTP
- clean URLS are not a requirement for REST
- Hyper-focus on URIs can make designs non-RESTful
What is REST
REST - Representational State Transfer - is an architectural style that describes how the Web works.
REST and SOAP
REST is an architectural style. SOAP is an implementation detail for RPC-style systems.
- Contract is the uniform interface
- Actions semantics are specified by the uniform interface and state transitions are specified by hypermedia controls embedded in representations
- Error semantics are specified by the uniform interface
- Caching supported by all intermediaries which understand the uniform interface
- Server owns the URL namespace
- Inputs and outputs are tied to the media type specification
- Tied to the uniform interface of the supporting protocol
REST and Richarson’s Maturity Model
Leonard Richardson has described the path towards REST in an incremental fashion:
- Level 0: POX (Plain-Old-XML)
- Level 1: Resources
- Level 2: HTTP Verbs
- Level 3: Hypermedia - RESTful
Deriving REST from its Constraints
Getting to REST
Define the architecture design of REST by applying constraint-driven design, that is, by identifying the forces that influence the system behavior and then applying constraints so that the design works with those forces. As opposed to requirements-driven approach, REST maps the business domain onto the architectural domain instead of mapping the architectural domain onto the business domain.
Some falacies of distributed computing that illustrate the forces that REST was designed to take into accounting are:
- Network reliability (Network is reliable)
- Latency (Latency is 0)
- Bandwidth (Bandwith is infinite)
- Security (The network is secure)
- Network topology (The network topology doesn’t change)
- Administration (There is only one administrator)
- Transport cost (Transport cost is 0, Infrastructure cost is 0)
- Heterogeneous network (All nodes on the network are the same)
- Complexity (Everyone who uses the system has the enough knowledge on how to use the system properly)
Contraints towards REST
The constraints applied towards building a RESTful system are: * client-server * stateless * cache * uniform interface * layered systems * code-on-demand
Which are explained below:
The goal of this contraint is separation of concerns.
- security, administration, heterogeneous network and complexity
- portability of clients, scalability and evolvability
The Server should be able to get all the information it needs to process a client request from the request itself and not from any additional context information that the server would be responsible for maintaining (like session state).
- Network reliability and topology, complexity and administration
- Reliability (state only exists in one place at any point in time)
Response from a server must be specified as cachable or non-cachable. This way we can take the advantage of using multiple layers of caching.
- latency, bandwidth, transport cost
- Scalability - your application can handle more clients
The uniform interface allows different nodes to communicate with one another via a standard mechanism. It represents the contract between client and server. The elements of the uniform interface are:
Identification of resources (a client consumes services capabilities by interacting with resources). In terms of HTTP, this will usually be a URL.
Manipulation through representations. (XML or JSON representation of the resource)
Self-descriptive messages - a message should contain the metadata needed for a client or server to do something with it
Hypermedia as the engine of application state (HATEOAS). The server generates links that describe ways to progress through a workflow.
- Network reliability, topology, administration, heterogeneous network and complexity
A component in a system can only know about the components to which it is directly communicating. This results in a loosely coupled system.
- Network topology, complexity, security
Code On Demand
- Helps to manage complexity
- The trade-off is visibility
Elements of a RESTful Architecture
- Components and connectors
- Control Data
The processors of resource requests and representations in an application. Units that work together in a RESTful design. Categorized by role:
- Origin Server (owns url space)
- User Agent (web browser, mobile device, etc)
- Gateway (represent multiple origin servers to the network)
- Proxy (represent multiple user agents to the network)
Represent activities involved in accessing resources and transferring respresentations. They can be thought as the set of possible interfaces that the components can implement to accomplish its work. the Roles provide interface for components to implement.
The most common types are:
- Resolver (translates resource identifier into whatever the right address format is so components can make a connection, f.i. DNS). They provide a level of indirection between components.
- Tunnel (relays communication accross a boundary, f.i. proxies and SSL)
A component can implement one or more connectors. For instance, a proxy implements at least the client and server connector, and usually implement all of these connectors detailed aboved.
Can be any named information or concept. A resource maps a concept to a set of entities over time. There is a many to many relationship between named concepts and entities, where a concept is a resource and the entities are representations.
For instance, I, Jaime, am a person resource, and there are many ways in which I can be represented: by my personal id, a photograph, a business card, etc.
If a resource is a unique concept within a system, then there should be a way to identify this resource, a resource identifier. The resource identifier, is how a server makes a resource available for interaction. A resource identifier should not change very frequently.
A way that we could identify resources would be:
A resource will also have resource metadata that will describe the resource further. (f.i. E-tag, location, etc)
If a resource is a concept, a representation is something concrete, a resource state at a given point in time. It can be any sequence of bytes. A resource can have multiple available representations.
The multiple existence of representations for a given resource supports the heterogeneous interoperability so fundamental to the concept of REST. This will allow a service to provide an unlimited number of representations tailored for very different clients.
Content negotiation is the process of selecting the best representation of a resource. It can be server-driven or agent-driven, based on the authority that determines which representation of a resource to use.
Representations can also have metadata as additional data that describes the representation, it helps the clients and servers on how to process the bytes. An example could be the MIME-types (application/json, application/xml…), encoding, language, character set, etc.
Control data is the information that describes the message sent between components of a RESTful design. It provides the semantics for the message exchange. The messages should be self-describing. It can be used to describe an intended action, the meaning of a response or override the default behavior of a connector.
In the case of HTTP, the control data are information such as the HTTP verbs, the HTTP status codes and additional HTTP headers that provide semantics within the messages being sent.
Hypermedia is the way to initiate state transitions in REST. It consists in using links within resource representations to describe the possible actions that can be performed on a given resource (or how to reach certain relationships of this resource). It dramatically decreases the client and server coupling by reducing the number of URLs the client needs to know about. Using hypermedia, the server can unilaterally own the URL structure and evolve as desired in the future.
A hypermedia control is a device within a representation that allows the use of hypermedia within the representation. In the case of HTML, the anchor tag is a hypermedia control, in the case of json or XML, there are no existing hypermedia controls and the server owner needs to provide them herself.
Following with the example of HTML, the snippet of code below represents a hypermedia link to GET the relationship child. A client built to rely on this hypermedia control should be implemented to run against the relation child and not the specific url in the href attribute.
<a href="http://localhost:8080/children/john" rel="child"> John Doe </a>
Designing RESTful Services
As an example, designing a bug tracking system using RESTful services would consist on:
- Discover bugs
- Add a new bug to the backlog
- Activate a bug
- Complete a bug (move to working and done)
Identifying the state transitions
- (entry) => new bug in backlog
- (backlog) => move to working
- (working) => move to backlog or done
- (done) => move to working
Identifying the resources
- GET: fetch hypermedia elements to navigate and to add a new bug to the backlog
- GET: fetch the list of bugs in the backlog
- POST: add a new bug to the backlog
- GET: fetch the list of bugs being worked on
- POST: activate the bug
- GET: fetch the list of bugs that are done
- POST: complete a bug
Design the representation/media type
- Base format (XML, JSON, HTML, etc)
- Read-only (client does not transfer data)
- Predefined (transfer bodies defined in the media type documentation that clients learn to use)
- ad-hoc (details about valid transfer elements are sent to the client in the representation - HTML forms)
- Specific: type is tightly bound to the business domain (custom schema)
- General: type is bound to a general domain, such as invoices or lists (ATOM)
- Agnostic: type is unrelated to a specific domain (HTML)
- None: client does not have any flow identifiers
- Intrinsic: identifiers are built into the media type design
- Applied: identifiers are applied using decorators (HTML rel and class)
- Base format: HTML
- State transfer: ad-hoc
- Domain style: agnostic
- Application flow: applied
Need elements for:
- list of bugs
- link template for moving a bug to backlog, working or done. These links will exist or not based on the type of representation. These will be hypermedia controls.
- link template for adding a new bug. Also a hypermedia control.
- Navigation links
Versioning in REST is based on versioning the uniform interface, that is, you can:
- version within the representation (when the semantics of a representation don’t change, i.e. adding new fields)
- version the representation (when the semantics of a representation change, i.e. renaming a field)
- version the resource (when the server cannot keep the semantics of mapping a resource and its associated entities i.e. creating a new resource/resource identifier/url)
Designing RESTful Clients
Written by Jaime González García , Front-end software engineer, tinkerer and master of the arcane arts. You should follow him on Twitter where he shares useful stuff!Follow @vintharas