3

A straightforward question: if I am building a stateless client, which 'changes page' between requests, how do I properly consume a hypermedia API?

A key point of course is that the client should not construct URLs. If we were to for example fetch a collection of some kind (let's say fruits), each collection entry would feature a URL to link to the individual fruit resource in the API. Great.

[ { "name": "Apple", "url": ".../fruits/15" } ]

However in my client, after presenting a list of fruits, I wish to link the list through to a different front-end page with details for the fruit. Such a details page should of course be bookmark-able, etc. The precise structure of the front-end URL is I realise, philosophically, of little concern - but it is of practical interest to the question below.

<a href="?">Apple</a>

The question then is, upon loading a fruit details page, how does the client with no current context decide on the API URL to GET?

/my/frontend/stuff/fruits/{?}

Now what :o?

A solution which initially springs to mind is to have an 'item' URL template in the collection response, and to use the named parameter(s) therein to construct the page URL. The details page would then query the API to recover the same 'item' URL and implant the parameter(s) it was passed. This doesn't seem ideal, however it does achieve the desired decoupling.

Thanks in advance.

jstephenson
  • 2,170
  • 14
  • 14

2 Answers2

4

A web browser is the stateless client most familiar to many users. What you are asking for is known as URI templating and is supported by various hypermedia formats. For example, in HTML:

<form action="/api/fruits" method="GET">
  <input type="number" name="id" value="1" min="1">
  <button type="submit">Get Fruit</button>
<form>

will of course generate GET requests to the URI /api/fruits?id=1 when submitted.

Other hypermedia formats such as HAL allow templating anywhere in the URI, and are better suited to web applications than HTML. You need to look into the templating mechanisms supported by your preferred hypermedia representation format or switch to a format that supports what you need.

Of course, in HTML due to poor templating, we have to list every desired URI and paginate long lists:

<a href="/api/fruits/1/">Apple</a>
<a href="/api/fruits/2/">Banana</a>
<a href="/api/fruits/3/">Citrus</a>
...
<a href="/api/fruits/?page=2" rel="next">Page 2</a>

To be honest though, if users are going to directly input IDs, you should probably allow HTML and query string parameters too. It will help third-party client developers when they are building against your API, and it's availability will help if you ever need to debug with end users. Just point them to a URL and ask "Does it work if you go here?"

Community
  • 1
  • 1
Nicholas Shanks
  • 10,623
  • 4
  • 56
  • 80
  • Is this in agreement, then, with the closing paragraph of my question? – jstephenson Jul 15 '13 at 11:10
  • Yes. Sorry, should have made that explicit in my answer :-) – Nicholas Shanks Jul 15 '13 at 11:19
  • Think this more or less answers the question, then. Thanks. – jstephenson Jul 15 '13 at 11:48
  • Hmm, I somehow only saw the first revision of this question when I came to answer it, perhaps via some direct link, I don't recall now. I would not have bothered saying "What you are asking for is known as *URI templating*" had I seen rev 2 of your question! Oh well. Glad it helps you. The main point really was **choose a suitable hypermedia format** for your API. I also expanded my answer a bit with an additional paragraph. – Nicholas Shanks Jul 15 '13 at 12:15
  • I am saying have two ways to access the data, one using canonical pretty URLs, and another that HTML can use, that has query strings (so you can use `
    `). You can just redirect from the latter to the former, but I would only do that for GET requests, just to be safe. This may be of great utility later on when you are trying to debug a customer's problem and they can't use the stateless client app, or the bug is in the client.
    – Nicholas Shanks Jul 15 '13 at 12:59
1

If I understand the problem correctly, there are two steps in the workflow:

Step-1: Client – GET(/api/fruits/)

  • Returned: [{“name” : “Apple”, “Id” : 1 }, {…}]

Step-2: Client – GET(/api/fruits/1/), GET(/api/fruits/2/), …

  • Details of each fruit is returned

The client must already know the “root” URL- “/api/fruits/” in order to get the list in Step-1. For it to get the individual fruit details as in Step-2, the client concatenates the “root” URL - “/api/fruits/” and “Id” returned in Step-1.

Not sure if you are familiar with the popular javascript framework Backbonejs. Its model supports this out of the box. I believe that most other frameworks should support this type of workflow as well.

You can take a look at these backbone specific links as examples:

Hope it help

Ming Chan
  • 1,938
  • 11
  • 21
  • I appreciate your response, but the question relates to the integration of a 'stateless' client with a hypermedia driven API. – jstephenson Jul 04 '13 at 21:12