REST-Based API Design
This is a continued blog post series. You can find the first post here.
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
— Roy Thomas Fielding
Chapter 7 starts with this quote. Hmm how many know this. I often hear people talk about REST as synonymous with any http based Remote Procedure Call (RPC) API. But WORDS has specific meaning. And here we are talking about REST, in its original meaning, suitable for hypermedia data transfer.
If you ever wanted to know what REST really means then this chapter is for you.
The chapter explains the following truth’s about REST:
REST is about distributed systems
REST was defined in a dissertation by Roy Fielding. James encourage us to read it since its not only about API’s but as much about constraints for evolvable distributed systems.
REST was never about CRUD
Even though many people associate REST with JSON based Create, Read, Update, Delete (CRUD) style API, this was never the essence of REST.
REST Is Client/Server
The fact, that the Client is separated from the sever, gives a high degree of decoupling and evolvability. The Client User Interface can change with out affecting the Server. This makes an API suitable for a generic product, since multiple clients can define different user interfaces.
REST Is Resource-Centric
REST Is Message Based
Keep in mind that an API is a conversation. Focusing on the message aspect of REST is important, as the chapter articulates here:
“Readers of Fielding’s dissertation may have noticed that it focuses on the message exchange between client and server. Notice the use of the terms REST messages and self-descriptive messages in the paper. REST-based API design goes beyond the properties within a JSON or XML representation.”
The request is a command that tells the server what to do.
However, other parts than the message body must not be neglected. The URL path, URL query parameters, and HTTP request/response headers must all be considered as part of the design process. Focusing only on the message body results in an incomplete design.
REST Supports a Layered System
Many API implementations never comes beyond the JSON, CRUD level and never gets to caching and other middleware that http and REST supports. The design should allow middleware to do caching, rate limiting, authentication and load balancing.
REST Supports Code on Demand
Hypermedia Controls
Hypermedia and HATEOAS gets explained. HATEOAS gives the client possibility for machine based discoverability. Most readers will probably know about REL links that links to related resources and permitted actions. But other kinds of hypermedia controls exist as well.
- Index hypermedia controls: Offer a list of all available API operations, typically as an API homepage.
- Navigation hypermedia controls: Include pagination links within payload responses or by using the Link header.
- Relationship hypermedia controls: Links that indicate relationships with other resources or for master-detail relationships.
- Context-driven hypermedia controls: Server state that informs the client what actions are available
It is the fact, that each resource has a unique URL in REST, that allows for hypermedia controls. This is an advantage that the REST API style has over other styles like GraphQL, gRPC and older network API styles and messaging specifications such as SOAP and XML-RPC.
When to choose REST
Choose REST for generic API, that allow independent development of multiple clients.
Consider gRPC when performance needs to be improved, but at the cost of closer coupling between client and server.
Consider standard RPC, for simplicity and if the payload is optimized for a specific client side application.
A REST API can be supplemented with a query API like graphQL.
REST API Design Process
Step 1: Design Resource URL Paths
Create a new table for the REST API Design. Define the resource path for each operation. Tip: Only use nested resources if it improves the design. When doing a bottom up design from a database one could be tempted to design URL’s as nested resources like the following:
GET /users/{userId}/projects/{projectId}/tasks/{taskId}
Often it’s better to avoid this since it makes it more complicated for the client. In the example above, the taskId is unique anyway and the task can be retrieved with out supplying the userId and projectId.
Step 2: Map API Operations to HTTP Methods
You need to assign http verbs like POST, GET etc.. This section gives in depth guidance on when to use what. Add the Http methods in a new column in the schema.
Step 3: Assign Response Codes
Step 4: Documenting the REST API Design
Chapter 13 goes into detail about various documentation formats. One such format the OpenAPI Specification,
which can be read and written using swagger.
The important point is to supply a machine readable documentation format, so one can take advantage of all the tooling like code generators and html generators for visualizing the documentation.
Another recommendation is to make sequence diagrams to validate the model. Remember that an API is a conversation between the user and the System. Make sure that the API operations allows for a natural flow that in the end yields a useful outcome for the user.
Step 5: Share and Gather Feedback
Representation Format
The chapter suggests 4 different representation format categories.
Category | Overview |
---|---|
Resource Serialization | The representation reflects the serialization of a resource into various formats, e.g., JSON, XML, Protocol Buffers, and Apache Avro |
Hypermedia Serialization | A serialized representation with support for embedded hypermedia controls |
Hypermedia Messaging | A general message format that supports resource properties with hypermedia controls |
Semantic Hypermedia Messaging | A general message format that supports semantic field mapping with hypermedia controls |
Resource Serialization
New binary formats are protocol buffers and apache avro
Hypermedia Serialization
{
"bookId": "12345",
"isbn": "978-0321834577",
"title": "Implementing Domain-Driven Design",
"description": "With Implementing Domain-Driven Design, Vaughn has made an
important contribution not only to the literature of the Domain-Driven Design
community, but also to the literature of the broader enterprise application
architecture field.",
"_links": {
"self": { "href": "/books/12345" }
},
"_embedded": {
"authors": [
{
"authorId": "765",
"fullName": "Vaughn Vernon",
"_links": {
"self": { "href": "/authors/765" },
"authoredBooks": { "href": "/books?authorId=765" }
}
}
]
}
}
Hypermedia messaging
“consider that teams will no longer need to argue about what the JSON or XML payload should look like. Instead, they focus on the resource representations, relationships, and hypermedia controls within the message format itself. No more meetings to decide if a data wrapper is required around a JSON-based response!”
Semantic Hypermedia messaging
Semantic hypermedia messaging is the most comprehensive category, as it adds semantic profile and linked data support, making APIs part of the Semantic Web.
- https://schema.org/
- https://www.hydra-cg.com/spec/latest/core/
- https://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html
- http://hyperjson.io/spec.html
- https://json-ld.org
- https://www.odata.org
{
"uber" :
{
"version" : "1.0",
"data" :
[
{"rel" : ["self"], "url" : "http://example.org/"},
{"rel" : ["profile"], "url" : "http://example.org/profiles/books"},
{
"name" : "searchBooks",
"rel" : ["search","collection"],
"url" : "http://example.org/books/search?q={query}",
"templated" : "true"
},
{
"id" : "book-12345",
"rel" : ["collection","http://example.org/rels/books"],
"url" : "http://example.org/books/12345",
"data" : [
{
"name" : "bookId",
"value" : "12345",
"label" : "Book ID"
},
{
"name" : "isbn",
"value" : "978-0321834577",
"label" : "ISBN",
"rel" : ["https://schema.org/isbn"]
},
{
"name" : "title",
"value" : "Example Book",
"label" : "Book Title",
"rel" : ["https://schema.org/name"]
},
{
"name" : "description",
"value" : "With Implementing Domain-Driven Design, Vaughn
has made an important contribution not only to the literature of the Domain-
Driven Design community, but also to the literature of the broader enter132prise
application architecture field.",
"label" : "Book Description",
"rel" : ["https://schema.org/description"]
},
{
"name" : "authors",
"rel" : ["collection","http://example.org/rels/authors"],
"data" : [
{
"id" : "author-765",
"rel" : ["http://schema.org/Person"],
"url" : "http://example.org/authors/765",
"data" : [
{
"name" : "authorId",
"value" : "765",
"label" : "Author ID"
},
{
"name" : "fullName",
"value" : "Vaughn Vernon",
"label" : "Full Name",
"rel" : "https://schema.org/name"
}]}]},
]}]}}
Common REST Design Patterns
I’m nearly replicating the whole book.
James lists 5 different REST design patterns
- Create-Read-Update-Delete
- Extended Resource Lifecycle Support
- Singleton Resources
- Background (Queued) Jobs
- Long-Running Transaction Support in REST
You should really get the whole book
Summary
A really extensive chapter, that shows how many possibilities REST offers. Something that many companies and people are not utilizing or are not even aware of.
The chapter is an eye opener in this regard and explains REST. The subject is big, which the amount of linked resources suggests; resources that we can explorer further. What we have by now, is a great overview and an overall understanding of what REST really is.