REST API — Back to Basics


When it comes to designing the REST APIs, we primarily brainstorm over below points.
- Identifying Resources — So what are resources ? Resources are the entities or objects in database . Am I right on this ? Ok then what about /api/v1/user/unsubscribe ? Am I breaking the REST rules here?
- Designing URLs — For sub-resource, it should always be something like this /api/v1/campaign/123/lesson/345. Isn’t it beautiful. Ok so what about accessing lesson directly ? /api/v1/lesson/345 . Some may argue that you can not access lesson directly because it is sub-resource of campaign. But what do I do if I have to do ? Am I breaking the REST rules again in doing so?
- API Response — Just return everything ( or almost everything). Some may argue it saves lots of repetitive requests and client would have everything that is require for the next 5 operations ? Ok, then why don’t the server just return HTML rendered web-page to the client so it does not have to do anything
- Storing application data on server side — It is rare but its there. Can we store the application data like session on server ? If not then why not and how come it is related to REST API at all ?
Above are the points over which we have always gotten into discussion with our colleagues. Sometimes we get it right and most of the time we do it wrong.
In this post, I will try to address these issues by going back to the thesis of Roy Fielding’s dissertation Architectural Styles and the Designs of Network Based Architectures
REST
REST is the Representational State Transfer, more importantly, it is an architectural style which was introduced by Roy Fielding in 2000 in his dissertation Architectural Styles and the Designs of Network Based Architectures
So the REST API that we talk about today are basically nothing but REST System build over HTTP. So your REST API architecture should adhere to the REST architecture constraints.
Characteristics of REST Architecture:
It is a client and server model so there must be client and server in the architecture.
It means for implementing REST, architecture should have a client and server. In other words, a standalone desktop application can not be mould into REST. In REST API, we always do have a client and server.
It is a stateless client and server model — Address point issue number 4.
It signifies server must not store any application data that is require to serve subsequent requests from client. This constraint ensure reliability, visibility and scalability of the architecture.
** This constraint does not restrict what can be store on client side.
It ensures reliability in the sense in case of partial failure of a system it is easy to recover because every client request is self contained ( not dependent on previous or future request).
It ensures visibility, if there is a request analyser analysing requests then its has just to look at a single request to understand its natures without worrying about the pending or previous requests client has served.
It ensures scalability, if server is not storing any application data then it can be scaled at large.
With this constraint comes the tradeoff of degraded network performance because of sending repetitive data to the server. This issue is address by below characteristic.
It is a Layered Client Cache Stateless Server Model — Address a part of issue number 3
It means REST architecture could have multi level cache at client and server ends. This constraint was added to improve network efficiency.
Uniform Interface — Important
Uniform interface means, Every REST architecture should have these elements
- Resource — There must be resources with their unique resource identifier i.e. unique url in REST APIs.
- Representations — Representation is the value/response of the Resource at a point in time based on the media-type. Resources can be manipulated only through their representations.
- Self Descriptive Messages — When server returns resource representation to the client then server should tell the client how to process the representation. Basically in terms of HTTP, content-type header should tell whether it is JSON or XML or some other format so that client can parse this representation.
- Hypermedia as the engine of application state —It means, once a client have initial response, then response should contains hyper links which allows a client to move to the next state of the application. Consider an example of web-browser accessing a url, once browser get the response then it automatically requests all resources needed to render the page completely.
REST API
Rather than being abstract, now lets understand the constraints REST APIs should adhere to.
Address issue number 1
Resource is the concept which has representation associated with it** i.e. some response at a point in time. It means a function /api/v1/user/unsubscribe could also be the resource as the information is associated with it.
** There might be the case when resource is mapped to empty representation. This particular scenario can be seen when client requests the resource identifier ( URL ) of the S3 bucket where it can put the object like images. AWS while creating resource identifier maps it to empty representation. Later client put the object at the location to make concrete representation of the resource.
So following are the valid resources (not talking about whether they are good resource identifier or not )
/api/v1/user, /api/v1/user/unsubscribe
They are all valid resources and not tangent to the constraints put on resources.
- Representation is associated with them at a point in time.
- They are not bound to their representation i.e response.
Consider this /api/v1/users/user.txt to fetch user.txt. Is this a valid resource ? No this is not valid resource because it is bound to its representation i.e user.txt. If you rename file user.txt to clients.txt then you have to change the resource identifier as well. Resource identifiers should not change when there is change in representation.
Address issue number 2
Resources with different resource identifiers should be considered as different resource i..e /api/v1/campaign/123/lesson/7890 and /api/lesson/7890?campaign=123 are two different resources.
Fielding had not put any constraints on the format of resource identifier. Both of the above identifiers are valid. And you can access sub-resources directly without breaking any REST guidelines.
Actually, it is more about whether to keep flat url scheme or hierarchy scheme.
In the case, where you would like to distribute your APIs, its best to keep hierarchy url scheme because it enforce the client to follow patterns.
In the case, where you have to do admin tasks on resources irrespective of their hierarchy, it is best to keep flat url scheme. You should not expose these APIs to outside world.
* So your backend may have two sets of APIs one for clients which enforces hierarchy, throttling, API keys etc and another one is the flat url scheme just for admin purpose.
Address issue number 3
Web-server should return the response to the client only whatever is required for the current request without being aware of what was sent and what will be required to the client in future
Web-server should return the representation of the resource that is being asked for rather than combining with the representations of other resources that may required in future.
It makes it easy for the client to understand the resource data structure and eventually modification on the resource.It is also scalable because server just has to focussed on the resource that is being asked for rather than doing complex calculations of combining various resources into single representations.
Combining it with other resource representation also impacts the way you can use the cache on server side. If you store combined representation of resources in cache as a API response then you have to invalidate the whole response even though there are just modifications on one resource which again makes server processes unscalable.
Combining it with other resource representation impacts the performance of server massively and makes the client inflexible as with this representation, client wont be able to manipulate resource easily.
Lets extend this logic, way back ( pure client-server model ) when server used to return complete HTML representation of a web page, it used to cause the massive degradation of server performance. On the top of that client just becomes a viewer of the data with hands tied and blind folded to put any logic around it.
So server should only send representation that is being asked for and series of hyperlinks with self descriptions which allow client to move to the next state.
In API response, with the resource representation, if it contains the hyperlinks using which client can move to next state ( HATEOAS) then your REST APIs would be considered as Richardson Maturity Model Level 3 ( RMM Level 3).
Thanks for reading :) :).
I would love to hear your feedback and if you liked the post, please feel free to recommend and share . BbYe ..