Introduction
RESTful refers to representational state transfer which is used to abstract the state and the interaction of a resource over the HTTP protocol. A RESTful server will provide a representation of the state of the communication along with the transfer. Two differents clients requesting the same idempotent command on two servers but the same resource will generate the same result on a RESTful API.
This document will only, briefly, cover the general mindset over a RESTful development and, since RESTful systems are not normalized yet, it will only cover a vision of a good RESTful development. Still, the concept is quite strict. It is normal and intentional that the reference documents provided doesn't have the exact same vision of a RESTful API because following the guidelines by the book may cost a lot in processing and make the communication heavy in information. The most important part is to build yourself a toolkit full of tools you do understand completely. Once you have your toolkit you will be able to make the right decision for your API.
This document will not explain what is the HTTP protocol.
RESTful API
The general idea behind the representational state transfer (REST) is to use the full capabilities of the HTTP protocol in order to produce a common way to interact with any resources. Also, the state of the communication is neither kept on client or server side but within the communication between the two. Both must provide all the necessary information to fully complete the needs of both the client and the server. The server will return a status code meaningful and the client must understand it and make a request according to the information the server just provided. The only elements the client can be certain is the fact that the URI is permanent and the server will provide a status code on the request. The server however can't be certain of anything regarding the client but the fact that it will use the appropriate METHOD for the request. Therefore, the server must provide a meaningful status code and coherent information. It is also necessary that the server provide URIs for further navigation by the client.
It is important to stay coherent with your API(s).
HTTP as common interface
HTTP is a client/server based protocol defining methods to interact with the state of the resources of the server. These methods are GET, POST, PUT, DELETE, OPTIONS and HEAD. Altogether these operation covers the majority of the resources use cases: read, add, update and delete. OPTIONS and HEAD might seem left behind however they are used as the minimal documentation for your APIs. With such options on all given resources, many common pattern can be avoided such: "GET /createFoo", "GET /updateFoo", "POST /deleteFoo", etc. Those can be replaced by "POST /foo", "PUT /foo", "DELETE /foo". In other words, the actions verbs are directly supported by the protocol leaving each field a single task:
Field | Task | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Method | Defines the action to be applied on the resource(s).
Although most API only implement GET, POST, PUT, DELETE, I recommend the implementation of OPTIONS and HEAD for intelligent client programming. These two method give a lightweight minimal documentation on your services at runtime. PATCH should not be implemented since PUT exists for that purpose. If PATCH is implemented, it must do exactly the same work as PUT. | ||||||||||||||||||||||||||||||||||||||||||||||||
URI | Defines the resource(s) affected by the action e.g. /process?id=12345 | ||||||||||||||||||||||||||||||||||||||||||||||||
Headers | Describes the communication and the body content. | ||||||||||||||||||||||||||||||||||||||||||||||||
Body | Contains specifications on the actual action over the specified resource. May be seen as the parameters of the action over the method. The resource filtering informations shouldn't be in the body. Put them in the URI query string instead. |
Although many web services are Remote Procedure Call (RPC) oriented and would put functionality directly into the URI, it is NOT RESTful to do so. The relation between the task and the field is (1:1) and this rule must not be broken. The URI must be used to identify a resource.
Common language
This section briefly covers the basic idea of choosing the best languages to communicate between devices. REST is designed to be built on top of HTTP. However there is plenty more to design in the communication with HTTP.
HTTP headers and predictability
The most predictable way to built a REST server is to use all the tools how they were designed to be used. Therefore creating new header for the simple purpose of your API implementation is not something one would call predictable. Having an APi predictable will allow other devices to understand and use your services even if they are not specifically designed for that purpose.
HTTP body and extensibility
The HTTP body can carry any data and should be used to do so. The format of the data is not specified and is not limited to the following: JSON and XML. Plain text can be used for simple tasks. Although, it is important to consider the extensibility of the transferred data along with versioning. Even if JSON seems heavy it is extensible and more durable than plain text.
Resource definition
A RESTful API exposes resources. These resources are identified by URI e.g. /resource/1. The URI definition is complete and can identify any resources.
Uniform Resource Identification (URI)
Even if the URI is commonly used to pass any kind of silly stuff event action which are already supported by the methods e.g. /foo/bar/delete?key=value, the URI should be used as an identifier only. With the capabilities of an URI and knowing that the URI is a resource it becomes easy to apply a certain action over a given resource. It is not even RESTful it is just how the protocol should work.
You can find here some guidelines on how to treat the URLs nested in the body.
Collection
Resource is a vague concept and should be interpreted as the context needs it. Il is possible to have a resource representing a collection of element such : /order. This collection of resources is referenced by a single URI. Each element of the the collection can still be accessible through: /order/12345 or /order?id=12345. The general idea is to allow the client to execute an action over a group of resources. If this feature is not important, you don't need a collection.
That collection can then be filtered using query string such:
/order?date=01_01_2001&total=123456789.12
Composition
The composition of resource is all about setting the granularity of the presentation of resources. If two resources are strongly related (1:1) then they should be merged into a single coherent resource. It is important to hide as much as possible the implementation details so the resources presented seems homogenous.
As an example of composition take a Cafe. The cafe can have multiple information such customers, orders, supplies and so on. However, it is nice to be able to access the cafe resource for all the informations it has to give.
That Cafe, Foo's Cafe, could be identified as /fooscafe and would provide information like addresses or menu. These resources could be accessed individually but makes much more sense if the are accessed through the aggregation: /fooscafe/menu, /fooscafe/store.
Indeed, Foo's Cafe could have it's own domain such www.fooscafe.com and would have www.fooscafe.com/menu and www.fooscafe.com/store. It is indeed a better option.
Here's another example: /computer/1/motherboard, /computer/1/drive/sda0. Each element of a collection can also be a composition of more complex entities.
Navigation
Navigability is one of the most important part of the REST API. The client must never have to find which URI to call to execute an action on. The related URIs and the next step URI should be returned in the body e.g. An HTTP client requests "GET /invoice" to the server however the collection of invoices is too big to be returned into a single request (pagination). The result in JSON should look like this:
[ { "pageno": 1, "invoices": [ { "id": "INV12345" }, ... ], "self": "http://hostname/invoice?pageno=1" }, { "pageno": 2, "invoices": "http://hostname/invoice?pageno=2", "self": "http://hostname/invoice?pageno=2" }, ... ]
The next step of the HTTP client's navigation seems obvious. The HTTP client will call each page separately to get the invoices lists. The problem could be avoided that the flow is still obvious to the HTTP client.
Complex action system
The limits of the RESTful API is when actions must be merged. An example for this is the merging. Imagine that your have a REST server providing file versioning capabilities. It is a known issue that at some point your will have to merge files. How could this complex action be done in with HTTP methods? Many would at first extend the POST method, add an additional header or add a new method to the protocol. All these choices break predictability of the API. First of all, we have to analyse our needs. Will the files be merged on client or server side. If it is merged on client side the answer is simple: GET /file1, GET /file2 and POST /mergedfile. However, merging on the server side is not as simple but not least feasible. The first step would be to send the server a POST about your intention over the files to merge. The body could look like the following JSON:
{ "source": [ { "http://host/file1", "http://host/file2" ] ], "destination": "http://host/mergedfile" }
Then the server could respond with the metadata of the merged file.
It is more appropriate in this kind of server to build a permissive one than to
Security
REST doesn't specify any security system. In fact, HTTP have many ways to protect the information such different authentications and HTTP secure.
It is recommended to at least one layer of security. It could reduce the exposure to security failures greatly.
RESTful designs should not treat security. The HTTP server must be secured.
Compatibility and Versioning
Compatibility and Versioning are two topic strongly coupled.
Versioning is the action of naming unique states of a software.
Compatibility stands for the ability of a system to work with another system. These systems can either be two different systems or two versions of the same system.
With REST, versioning and compatibility aren't simple tasks. In order to facilitate those process, it is important to build your data models and your resources having those two goals in mind. In other words, software architecture is important.
Although HTTP is an extensible protocol, extending HTTP in order to support both versioning and compatibility is disrespectful to RESTful design. HTTP status codes must be used in order to let the client know the actual capabilities of the server.
If the server's API version or extensions are needed, it can be represented as a resource such: "/version" or "/extension". It is your own choice to support all the HTTP method on these resource. Keep in mind that the actions must remain coherent: Do not use a POST to update the version or the extension if the request does not provide, at least, an URI for the piece of software.
Forward and Backward compatibility
As long as the HTTP protocol is respected and the data transferred in the body is extensible enough, those two types of compatibilities should not be hard to satisfy. Although, keep in mind that your design will need them.
Extensibility
One of the strengths of a RESTful design built on top of the HTTP protocol is that is inherently highly extensible. New functionalities can be added without affecting any existing resource..
JavaScript, JQuery and REST utility
JavaScript is an interpreted programming language. It's interpreters are defined within the core of the HTTP client library. Meaning that Chrome and Firefox both uses two different interpreter which yields slightly different results. This being said, JavaScript code is obtained from your HTTP server and then ran on the client of your RESTful API.
JavaScript does not natively support HTTP requests such AJAX. In order to be able to dynamically load content of a web page, JQuery is the best tool to use. JQuery has an AJAX API which allows to dynamically request new content for the web page. These content can be small and easy to handle by your embedded HTTP server. They can also be generated on the go.
It is important to keep in mind that REST is not only designed for web pages. It can be used to publish different services over different networks of any size. Here are a few examples of REST utility:
- Commun interface for different purpose of information retrieval. See Google Glass API
- Domotics
- SUN Cloud API
Writer notes
If you would like to read more on the subject I would highly recommend:
http://stackoverflow.com/questions/16877968/call-a-server-side-method-on-a-resource-in-a-restful-way
This post is a "short" explanation of a RESTful solution over a complex question. It does cover most of the points mentioned above but with a context.
Lexicon
Word | Meaning |
---|---|
Idempotent (HTTP method) | The result of an idempotent action is the same even after multiple successive calls. |
Safe (HTTP method) | Safe actions do not modify resources. Their result can be cached or prefetched without any repercussion to the resource. |