Introduction
This is the first blog in a series of blogs on REST. In these blogs I’ll try to demystify the REST. I’ll discuss what REST is and some suggestions for how you can design good REST APIs.
First, let me acknowledge some of the sources of these posts. I’ve been teaching REST API’s for one of my favorite clients PayPal over the last year. In the process I’ve had the fortune of working with the PayPal services team. The discussions with these individuals and my students have led to a great number of insights on my side. In particular, I’d like to acknowledge Jason Harmon with whom I’ve collaborated on creating the courses that we currently teach at PayPal. Jason’s insight into REST and passion for good API’s are legendary.
The current plan is to provide a set of blog posts. As I build them, I’ll inject direct links into the below list:
- What is REST? (covered in this first delivery)
- Domain driven development of REST APIs
- Versioning of REST resources
- An extensive example of how I build REST API’s
- PATCH vs. PUT
- Controllers vs. event-soucing
Is REST services a new idea?
I actually once started an article on why REST is not new. However, halfway through the article, I had to stop and admit to myself that there are some quite new ideas in REST. I’ve seen similar ideas to REST in various books through the time. For example some of the ideas in Cheesman&Daniels book on “UML and Components” had many of the same design ideas as what was later contributed to REST.
This is not to discredit Roy Fielding. Fielding suggested the ideas that we now call REST in his PhD theses and I think his ideas are brilliant.
The main new ideas of REST in my opinion are:
- Services are organized around resources
- Resources have unique URL
- Resources can be manipulated through HTTP
- The encoding of the resources can be determined by the client
- The introduction of Hypertext (or more correct Hypermedia) to the API
All of these new ideas lead to some really interesting benefits. Probably the most important one is a great consistency in the way the API appear to the clients.
What is REST?
REST is short for REpresentional State Transfer. Of course, that doesn’t really convey it all, so let me give you my elevator pitch:
REST is an architectural strategy for defining API’s where the clients and service providers share a common information model and the client activation of the services takes the form of requests for lookup, updates or creation of information in the shared information model. The information model takes the form of sets of resources and their relationship.
The protocol of communication between the client and the service provider is HTTP where the resources are identified by a URI, the intent of the query or update of the information model is expressed through HTTP verbs and the format of the information exchange is defined by the content type. The desired content types(s) can be controlled by the client if the service provider supports more than one type.
What is a resource?
Central to the idea of REST is the concept of a resource. To help you understand what resources are, I would want to separate two different words to make the narrative a little clearer and also to allow me to draw parallels to those with an object-oriented background.
- Resource-Set
- A resource-set is a collection of resource instances. When communicating with a service provider a client would address the resource set to perform operations such as
- Create a new resource instance
- Find a resource instance
- For those of you with an object-oriented background, imagine the resource-set as a class
- For those of you that have a relational database background, imagine the resource-set as a table
- Resource-Instance
- A resource-instance represents an individual conceptual object that a client and the server agree upon
- Our operations on resource-instances are typically
- Read its state (or information)
- Update its state (or information)
- Remove it from our conceptual resource-set
- For those of you with an object-oriented background, a good analogy would be an instance/object
- For those of you with a relational database background, think of the resource-instance as a record
The analogies that I suggested for relational databases or object-oriented technologists may be helpful in the beginning, but you have to eventually make the leap to understand that the resource (set or individuals) are conceptual not physical.
Let’s illustrate with an examples from various domains:
- Hospital domain
- “Patients" is an example of a resource-set
- An resource-instance is “Joe Doe, a patient admitted to the hospital”
- “Admissions" is an example of a resource-set
- “Joe Doe’s admission to the hospital on 2/3-2015 11:01PM CST” is an example of a resource-instance belonging to this set
- Rental car domain
- "Rental car agreements” is an example of a resource-set
- “Sarah Smith’s rental at Hertz At San Francisco Airport on 2/3-2013 9:01 AM PST” is an example of a resource-instance belonging to this set
The point that the resources are based on a conceptual model is very important. The fact that we have a resource-set called Patients, does not necessary mean we have a table called patient in our implementation. All we are saying is that as a service provider (e.g., a hospital-admittence server), we understand what you mean by Patient and we have an API that allows clients to manipulate patients. We may for example provide a resource-set upon the URI http://api.hospitals.com/patients which allows you to lookup all our know patients instances (or resource-instances).
Whether a client is referring to a resource-set or a resource-instance is clear in every service invocation by the URI that they use. A service provider will publish one URI that refers to the resource-set. A resource-instance is always addressed by adding a unique identifier to the resource set. Let me give you a real-world example. At PayPal we have a resource-set that can be addressed at:
https://api.paypal.com/v1/wallet/payments
If I wanted to create new payments or find payments, I would use this URI. However if I wanted to read an resource-instance, in this case a specific payment, I would address that at:
https://api.paypal.com/v1/wallet/payments/293759715
Notice that the URI of the resource-instance is identified by the resouce-set + “/“ + the identifier of the payment.
The CRUDF idea of REST
REST suggest that most of the things we do as clients of services is to manipulate these conceptual resource-instances. In particular, we may Create, Read, Update, Delete and Find instances. Notice the F is not normally used. This may very well be my own invention. As I was writing this, I looked to see if someone else had used the same term. I did find SCRUD (S for search), BREAD (Browse, Read, Edit, Add Delete), so not an original though from my side. I’ll just continue using CRUD(F) as I’ve been using this term when teaching and I believe many of the readers of my blog are ex-students :)
Another idea in REST is that we’ll identify what we want to do by a combination of URI and HTTP verbs. That is, we can clearly see if the intention of any client request by simply knowing the URI and which HTTP verb. HTTP supports a set of verbs. Not all of them are used in REST. Most of us are familiar with the difference between GET and POST (GET is typically used to open a page in your browser, POST is often used to submit a form from your browser). In addition to the GET and POST, we also use PUT, PATCH and DELETE.
In theory, that gives us 10 combinations (two dimensions; instance vs set and the 5 verbs). In practice, we only use 6 combinations though.
Let me show you in a simple table.
URI (Set vs. Instance) | HTTP verb | Semantics |
---|---|---|
http://URI_OF_RESOURCE (set) | GET | FIND a set of resource-instances that belong to the specified resource-set |
http://URI_OF_RESOURCE (set) | POST | CREATE a new resource-instance and make it available from the resource-set |
http://URI_OF_RESOUCE/ID (instance) | GET | READ a resource-instance |
http://URI_OF_RESOUCE/ID (instance) | PUT | UPDATE a resource-instance |
http://URI_OF_RESOUCE/ID (instance) | PATCH | UPDATE a resource-instance. Notice that we already can do this with PUT. PATCH is an alternative to PUT whichI'll get back to in a later post. |
http://URI_OF_RESOUCE/ID (instance) | DELTE | DELETE a resource-instance |
Notice that leaves a set of combinations. Although these combinations are perfectly valid and the semantics of such operations can be defined, they are rarely used. Just for completeness though, let me give you the combinations and explain why they are seldom used:
- DELETE on a resource-set.
The semantic of this would be to delete all resource-instances in the resource-set. We don’t usually expose this for two reasons. - The operation is “too dangerous”
- It is difficult to handle partial failure. What if we managed to delete a subset of the resource-instances? Of course we can define the behavior and allow this combination, but it is usually not used in API’s I’ve studied
- PUT on a resource-set.
The semantic would be to replace reachable resource-instances in resource-set with the new list that we are “PUTting”. The reasons for this not typically supported is the same as for the DELETE on the resource-set - POST on a resource-instance.
I’m not sure what the semantics of such an operation would be, but I know from teaching that students have suggested using this when the client gets to specify the resource identifier. I think this is a bad idea. If you want to support client-derfined resource identifiers, the identifier should be part of the payload (more about that later).
A simple example
Let’s design a simple ToDo application. Let’s say we want to create a service that allows clients to produce a list of things to do. The todo-items describe what client wants to do and when the task is due.
The first thing to do is to try to define the resources. In this example the resource-model is very simple. In later blogposts I’ll show how to use domain models to find the resources. The only resource here is the list of todo items. The REST API may looks something like this
- To CREATE a new todo item
- URI = resource-set
- E.g.
- http://api.sample.com/todos
- HTTP verb = POST
- The data of the new todo item will be passed to the service in the body of the request
- To READ a specific todo item
- URI = resource-instance
- E.g.:
- http://api.sample.com/todos/123
- 123 is the resource-instance identifier
- HTTP verb = GET
- The data of the requested todo item will be passed in the body of the respose
- To UPDATE a specific todo item
- URI = resource-instance
- HTTP verb = PUT
- The updated todo item will be passed to the service in the body of the request
- To DELETE a specific todo item
- URI = resource-instance
- HTTP verb = DELETE
- To FIND a set of todo items
- URI = resource-instance
- HTTP verb = GET
- The set of resources will be returned to the client in the response body
Implementation of RESTful Service
There are some great technologies available that makes the creation of a RESTful service quite trivial. Here are some technologies that you may want to explore broken down by the programming language/platform they work on:
- Java
- There are a number of libraries available. I would recommend the use of JAX-RS based services such as:
- Apache Wink
- .NET/C#
- Python
- Scala
- Spray
- You can also use the JAX-RS providers since Scala integrates with Java
- Ruby
- PHP
- Node.js
Conclusion
In this article, I’ve highlighted some some of the basic principles of REST. In the next article, I’ll take a simple example of a functional API and design some REST resources.
View comments