Created
April 26, 2012 07:21
-
-
Save odrotbohm/2497116 to your computer and use it in GitHub Desktop.
Spring Data REST - Link representation options
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Current state (1.0.0.M1) | |
--------------------------- | |
+ Aligned with the XML definition of atom:link. | |
- Harder to work with for JavaScript clients | |
GET /root | |
200 OK | |
{ _links : [ { rel : "persons", href : "/root/persons" }, | |
{ rel : "accounts", href : "/root/accounts" }]} | |
2. Alternative | |
-------------- | |
+ Easier to work for JavaScript clients. | |
- Custom link scheme introduced | |
- Multiple links with same rel impossible (see below) | |
GET /root | |
200 OK | |
{ _links : { persons : "/root/persons", | |
accounts : "/root/accounts" }} | |
3. Problematic scenario with 2. | |
------------------------------- | |
A GET to a collection resource currently returns a list of links, not representations, which would create duplicated keys for the fields. | |
GET /root/persons | |
200 OK | |
{ _links : { person : "/root/person/1", | |
person : "/root/person/2" }} | |
This is of course invalid but we could tackle this problem in two ways: | |
3.1. Plain link lists without rels | |
---------------------------------- | |
As the rel for the returned links is implicitly known by the collection resource (a GET to a persons resource, returns links pointing to person resources). We could simply return a list of links then: | |
GET /root/persons | |
Accept: application/json | |
200 OK | |
[ "/root/person/1", "/root/person/2" ] | |
or | |
200 OK | |
{ _links : [ "/root/person/1", "/root/person/2" ] } | |
GET /root/persons | |
Accept: text/uri-list | |
200 OK | |
/root/persons/1 | |
/root/persons/2 | |
3.2. Return representations instead of links | |
-------------------------------------------- | |
Alternatively we could return a more verbose representation of the persons already: | |
GET /root/persons | |
200 OK | |
{ persons : [ { firstname : "Dave", | |
lastname : "Matthews" | |
_links : { self : "/root/persons/1" }}, | |
{ firstname : "Carter", | |
lastname : "Beauford", | |
_links : { self : "/root/persons/2" } | |
], | |
_links : { _next : "/root/persons?page=1&size20" } } | |
We did not decide for that approach in the first place as if done naively we might return all the resources which results in an unbearable payload and unnecessary network traffic. An approach to work around this is paging by default, which means we will return only a subset of the resources by default and provide links to navigate the collection. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It may feel weird but this is a very common case and question you will need to answer. I tend to agree treating them as separate resources is the right way to go. Nearly all the major APIs on the web separate out their API from their web site. Facebook, Twitter, Github, etc. So in those cases they're separate resources. Having complexity introduced at the HTTP routing layer in the name of REST "purity" smells of overengineering and unnecessary complexity to me. Browser Accept Headers also can't generally be relied upon, and a dedicated API subdomain separate from www is often desired.