RESTful API runtime discoverability / HATEOAS client design
Asked Answered
U

6

80

For a SaaS startup I'm involved in, I am building both a RESTful web API and a couple of client apps on different platforms that consume it. I think I've got the API figured out, but now I'm turning to the clients. As I've been reading about REST, I see that a key part of REST is discovery, but there seems to be a lot of debate between two different interpretations of what discovery really means:

  1. Developer discovery: The developer hard-codes copious amounts of API details into the client, such as resource URI's, query parameters, supported HTTP methods, and other details that they've discovered through browsing the docs and experimenting with the API's responses. This type of discovery IMHO necessitates cool linkage and the API versioning question, and leads to hard coupling of the client code to the API. Not much better than if using a well-documented collection of RPC's it seems.

  2. Runtime discovery - The client app itself is able to figure out everything it needs with little or no out-of-band information (presumably, only a knowledge of the media types the API deals with.) Links can be hot. But to make the API very efficient, a lot of link templating for query parameters seems to be needed, which makes out-of-band info creep back in. There are possibly other difficulties I haven't thought of yet since I haven't gotten to that point in development. But I do like the idea of loose coupling.

Runtime discovery seems to be the holy grail of REST, but I'm seeing precious little discussion about how to implement such a client. Almost all REST sources I've found seem to assume Developer discovery. Anyone know of some Runtime discovery resources? Best practices? Examples or libraries with real code? I'm working in PHP (Zend Framework) for one client. Objective-C (iOS) for the other.

Is Runtime discovery a realistic goal, given the present set of tools and knowledge in the developer community? I can write my client to treat all of the URI's in an opaque manner, but how to do this most efficiently is a question, especially over low-bandwidth connections. Anyway, URI's are only part of the equation. What about link templating in the Runtime context? How about communicating what methods are supported, aside from making a lot of OPTIONS requests?

Unicef answered 9/2, 2012 at 1:8 Comment(3)
Just a slight aside on your OPTIONS reference. You can use the 'Allow' header to communicate permitted resource operations outside of an OPTIONS request. Roy Fielding goes as far as considering the header as a form of hypertext - see here.Dg
tats a gr8 question, the key issues are given the list of applicable methods, should the client be able to form urls for the regular CRUD operation or will that be called as "out-of-band"? Say, if we provide links for CRUD operations as well, how do u do "form" s in json? May be if u r using application specific media types u dont need to do "forms", but wat is the standard way of discovering media-types(i.e json schema), will the process of discovering schema be considered as not "out-of-band" for clients??Standridge
xhtml looks so good and fluid, but if u have to do json, tat i guess is rather amorphous nowStandridge
D
19

This is definitely a tough nut to crack. At Google, we've implemented our Discovery Service that all our new APIs are built against. The TL;DR version is we generate a JSON Schema-like spec that our clients can parse - many of them dynamically.

That results means easier SDK upgrades for the developer and easy/better maintenance for us.

By no means the perfect solution, but many of our devs seem to like.

See link for more details (and make sure to watch the vid.)

Dyslalia answered 9/2, 2012 at 2:19 Comment(1)
Is there any standart to implement such a discovery service for our own APIs?Buchholz
A
12

Fascinating. What you are describing is basically the HATEOAS principle. What is HATEOAS you ask? Read this: http://en.wikipedia.org/wiki/HATEOAS

In layman's terms, HATEOAS means link following. This approach decouples your client from specific URL's and gives you the flexibility to change your API without breaking anyone.

Antemundane answered 9/2, 2012 at 6:1 Comment(0)
C
6

You did your home work and you got to the heart of it: runtime discovery is holy grail. Don't chase it.

UDDI tells a poignant story of runtime discovery: http://en.wikipedia.org/wiki/Universal_Description_Discovery_and_Integration

Catechumen answered 9/2, 2012 at 1:52 Comment(0)
S
6

One of the requirements that should be satisfied before you can call an API 'RESTful' is that it should be possible to write a generic client application on top of that API. With the generic client, a user should be able to access all the API's functionality. A generic client is a client application that does not assume that any resource has a specific structure beyond the structure that is defined by the media type. For example, a web browser is a generic client that knows how to interpret HTML, including HTML forms etc.

Now, suppose we have a HTTP/JSON API for a web shop and we want to build a HTML/CSS/JavaScript client that gives our customers an excellent user experience. Would it be a realistic option to let that client be a generic client application? No. We want to provide a specific look-and-feel for every specific data element and every specific application state. We don't want to include all knowledge about these presentation-specifics in the API, on the contrary, the client should define the look and feel and the API should only carry the data. This implies that the client has hard-coded coupling of specific resource elements to specific layouts and user interactions.

Is this the end of HATEOAS and thus the end of REST? Yes and no.

Yes, because if we hard-code knowledge about the API into the client, we loose the benefit of HATEOAS: server-side changes may break the client.

No, for two reasons:

  1. Being "RESTful" is a property of the API, not of the client. As long as it is possible, in theory, to build a generic client that offers all capabilities of the API, the API can be called RESTful. The fact that clients don't obey the rules, is not the API's fault. The fact that a generic client would have a lousy user experience is not an issue. Why is it important to know that it is possible to have a generic client, if we don't actually have that generic client? This brings me to the second reason:
  2. A RESTful API offers clients the option to choose how generic they want to be, i.e. how resilient to server-side changes they want to be. Clients which need to provide a great user experience may still be resilient to URI changes, to changes in default values and more. Clients doing batch jobs without user interaction may be resilient to other kinds of changes.

If you are interested in practical examples, checkout my JAREST paper. The last section is about HATEOAS. You will see that with JAREST, even highly interactive and visually attractive clients can be quite resilient to server-side changes, though not 100%.

Seat answered 2/11, 2015 at 11:15 Comment(0)
M
1

I think the important point about HATEOAS is not that it is some holy grail client-side, but that it isolates the client from URI changes - it is assumed you are using known (or developer discovered custom) Link Relations that will allow the system to know which link for an object is the editable form. The important point is to use a media type that is hypermedia aware (e.g. HTML, XHTML, etc).

Motte answered 11/12, 2012 at 15:32 Comment(0)
B
0

You write:

To make the API very efficient, a lot of link templating for query parameters seems to be needed, which makes out-of-band info creep back in.

If that link template is supplied in the previous request, then there is no out-of-band information. For example a HTML search form uses link templating (/search?q=%@) to generate a URL (/search?q=hateoas), but nothing is known by the client (the web browser) other than how to use HTML forms and GET.

Brabble answered 6/8, 2013 at 15:3 Comment(1)
indeed there is no out-of-band info - the client is responsible for expanding out the uri templates using the supplied resource/instance data (and should know how to do this) - json-schema.org/latest/json-schema-hypermedia.html#anchor18Canice

© 2022 - 2024 — McMap. All rights reserved.