restdiscoveryhateoas

HATEOAS - Discovery and URI Templating


I'm designing a HATEOAS API for internal data at my company, but have been having troubles with the discovery of links. Consider the following set of steps for someone to retrieve information about a specific employee in this system:

  1. User sends GET to http://coredata/ to get all available resources, returns a number of links including one tagged as rel = "http://coredata/rels/employees"
  2. User follows HREF on the rel from the first request, performing a GET at (for example) http://coredata/employees

The data returned from this last call is my conundrum and a situation where I've heard mixed suggestions. Here are some of them:

  1. That GET will return all employees (with perhaps truncated data), and the client would be responsible for picking the one it wants from that list.
  2. That GET would return a number of URI templated links describing how to query / get one employee / get all employees. Something like:

    "_links": {
        "http://coredata/rels/employees#RetrieveOne": {
            "href": "http://coredata/employees/{id}"
        },
        "http://coredata/rels/employees#Query": {
            "href": "http://coredata/employees{?login,firstName,lastName}"
        },
        "http://coredata/rels/employees#All": {
            "href": "http://coredata/employees/all"
        }
    }
    

I'm a little stuck here with what remains closest to HATEOAS. For option 1, I really do not want to make my clients retrieve all employees every time for the sake of navigation, but I can see how using URI templating in example two introduces some out-of-band knowledge.

My other thought was to use the RetrieveOne, Query, and All operations as my cool URLs, but that seems to violate the concept that you should be able to navigate to the resources you want from one base URI.

Has anyone else managed to come up with a good way to handle this? Navigation is dead simple once you've retrieved one resource or a set of resources, but it seems very difficult to use for discovery.


Solution

  • Option 2 is not too bad as you're using RFC 6570 to characterize the URI patterns; while HATEOAS is usually stated in terms of not having clients synthesize URIs, if a server is prepared to make guarantees on the URI template and to tell it to clients explicitly in a standard format, it's acceptable. (I would be tempted to have the “list all employees” URL be without the all suffix, so as to distinguish it from the employee with that ID; the client should not — in principle — know what an employee ID looks like.)

    In fact, the main problem is actually that clients have to understand what those tag URIs mean; there's just no real way to guess that “http://coredata/rels/employees#All” means “list all employees”. That's where you get into embedding knowledge in clients, semantic labeling, etc. and HATEOAS doesn't really address those things.