4

I've been trying to build a hypermedia based API. Things seem working well. Say when I fetch /books/isbn/12313441213 I get something like this:

<book>
  <id>123</id>
  <name>Hypermedia APIs</name>
  <description>Basic api design techniques</description>
  <tags>
    <tag>rest</tag>
    <tag>api</tag>
    <tag>service</tag>
  </tags>
  <authors>
    <link rel="author" uri="/authors/id/22" />
    <link rel="author" uri="/authors/id/18" />
  </authors>
</book>

Now I can traverse the authors from this resource. When I fetch /books/by/author/id/18 I get something like this:

<books>
  <book id="123">
    <name>Hypermedia APIs</name>
    <link rel="self" uri="/books/id/123" />
  </book>
  <book id="191">
    <name>Chef Recipes for Rails Developers</name>
    <link rel="self" uri="/books/id/191" />
  </book>
  <book id="220">
    <name>Rails 4 Cookbook</name>
    <link rel="self" uri="/books/id/220" />
  </book>
  <book id="292">
    <name>Ruby 102</name>
    <link rel="self" uri="/books/id/292" />
  </book>
  <book id="432">
    <name>Semantic Architecture</name>
    <link rel="self" uri="/books/id/432" />
  </book>
  <book id="501">
    <name>Service Oriented Design</name>
    <link rel="self" uri="/books/id/501" />
  </book>
</books>

Which also seems to be working fine for me. Whether or not this way of uri templating is good, my question is around how practical to traverse links like this?

Considering you want the resource in full-depth (including author details), you have to make at least 3 calls to the server. Again for the collection, you have to make tons of calls to the server. Yes maybe I could utilize resource expansion here, but then why would I use hypermedia links at all since all of my clients will be using expanded resources in time.

I understand we are gaining lots by letting clients to traverse links (ie. if clients build relation based resource discovery, they will be impacted minimum when we change the api, or they are forced to get the most recent schema from the resource endpoint itself, etc). Then again, practicality of this approach, or the performance of this approach would kill the system.

Either I'm not getting something in hypermedia api design, or hypermedia api sounds great but it seems it's just a theoretical idea, not a practical one.

Any thoughts on this?

James Dolnewiy
  • 103
  • 1
  • 4

2 Answers2

2

It would be more traditional to use parameters:

GET /books?author=18

I would expect that the response would look more like:

Hypermedia APIs

You can also use a parameter to indicate what fields on sub-resources you want visible. Something like

GET /books/18?expand=author(name, birthday)

which would return the author's name and birthday as part of the author tag in the response. Then you can provide a reasonable default for how much author information users get when they ask for a book (maybe just the author's self and name), but they can get more details if they want by altering the parameter.

Those kinds of customization can help cut down on the number of calls that need to be made.

Another observation is that a lot of this data can be cached, either on the client or on intermediate proxies. It's not likely that much will change about a book or an author, so those resources can let the client cache them for a long period of time. Then there's no round trip at all - the client hits their own local cache for the data.

Eric Stein
  • 13,209
  • 3
  • 37
  • 52
  • Thanks for the answer Eric. URI templating part of my question is a controversial topic. I think both cases are valid based on what kind of capabilities you wanna build on top of your service. For the part where u mention the resource expansions, as I'm still puzzled why would anyone use hypermedia linkage in that case. I'm very positive soon dummy clients will adopt fully expanded resources. Only maybe conscious clients would be using API wisely. Caching might also be penalty considering schema updates, etc. Still I think there must be a better way or representation of this.. Don't you think? – James Dolnewiy Aug 08 '13 at 00:25
2

This is a great question of all the time. In fact, another big question is: who knows the traversal rels to reach a particular resource R?

For example to reach to "book-detail" resource the client have to make a call to the entry of your api eg "/" then using the rel "book-categories" get uri to book-categories then make a call to OPTIONS to see if GET operation is possible on that resource then do get the book categories, then get the rel to "books-in-category" resource ...etc which ultimately goes to "book-detail" resource. That traversal path to resource R should be part of the knowledge of the client. But don't hard-code the urls, just read the urls at run time. This is considering machine-to-human scenario. The inefficiency is still there. In the case of machine-to-machine scenario, an automaton that starts from "/" can go through your API and do certain processing to your resources. If the automaton has to reach to all resources in the tree (or may be state machine) then there is no inefficiency. But if the automaton needs to make a call to a resource down in the tree, and it knows only the entry point of the API then it will run in to the issue of making several calls to reach it's point.

Many people will tell you to introduce caching using etags and/or memcached, but caching is to augment performance, you cannot depend on caches 100% because caches get stale, so in those cases the code for traversing resources R1 to Rn should be in your client.

check my question on: https://stackoverflow.com/questions/15214526/why-hypermedia-api

But to answer your question on practicality: if you have a business work flow in which the client is required to go to resource R1 then R2 then ... Rn and you want to enforce that flow, hypermedia is practical. I'm assuming that there are no direct calls to Resource Rx with out going through R1 -> R2 ->... Rx-1.

Community
  • 1
  • 1
Rose
  • 2,792
  • 4
  • 28
  • 42
  • Enabling private caching and setting a max age on a api's root resource is sufficient to eliminate a large amount of redundant calls. Etags and memcached are not required. Link hints can be used prevent the need for an OPTIONS round trip. There is also no reason why a client cannot chose to persist a bookmark for future usage as long as it can handle the consequence of the bookmark becoming invalid at some later point. – Darrel Miller Aug 15 '13 at 01:50
  • @DarrelMiller it is not just the api's root resource, it totally depends on the depth of the resource sequence. In reality resource are structured as a state machine but for the sake of simplicity I want to consider it as a tree. So you should consider all resources from the root resource to the leaf resources and see if caching is appropriate; it's not just the root resource that has to be efficient. Remember in hypermedia, the root resource doesn't necessarily give you all resource URLs, it gives you only what is reachable from the root. – Rose Aug 15 '13 at 16:51
  • Agreed that the root isn't the only resource that may need to be cached to optimize efficiency. However, ideally your root to leaf traversal should be as short as possible. Also, I find a large % of LO traversals can be mapped to a single UI interaction, so there are no wasted round trips. – Darrel Miller Aug 15 '13 at 17:23