Hating on HATEOAS a little bit, thinking about it a lot

I've been thinking about how to enable HATEOAS on this web app, and it is a mind-bender. Django isn't quite up to it - but it does have a key feature of named links and URL generation that seems like a requirement for HATEOAS. To do HATEOAS, links need to be elevated to a higher status in the system.

For one, on the web, links are very different from the way software internals are organized. In software, and also in URLs, we have hierarchies: paths to files, paths to APIs, hierarchies of objects, and nested data structures.

Links are references between these hierarchically organized objects, and they allow you to bypass the hierarchies. We need graphs that have all different kinds of shapes, including cycles. (On the web, circular references are commonplace.) These links also have types of relationships associated with them.

So, the problem here is managing links. It's not dissimilar from the problem of routing URLs to classes or objects in a web app.

The web-server solution is to map the URL path to the file system's path. That's also PHP's basic solution. When you need more flexiblity, you introduce a layer of indirection via routers, so arbitrary paths can map to arbitrary pieces of code. Django's routes have names, and you refer to them by name; by using a name, you have another layer of indirection, and can change the URL in the future.

Links are somewhat like routes. They are decoupled from routes, and can be requested by any view, by name. A view will have numerous links, and should be selectable not only by name, but by type. If you want your "parent" link, you request the "parent" for yourself. What is the "parent"? It's configurable.

That's just the simplest situation. It gets more complex when you need to control access to resources. If a resource is inaccessible, the link shouldn't exist. (You don't want a 5** error.) That means you need to run your permissions tests when you're creating links.

That's going to be pretty slow so you need some caching mechanism or a precalculated access data structure where you can look up if you have access to a resource. It can be complicated.

The system should not produce links that go to nonexistent resources (4** errors). So there needs to be an initial attempt to check all the links against the classes and objects they reference.

Links also have a label, which is usually the title of the linked document. However, in an API, you're linking to resources. In some web applications, the users expect a small preview of the linked resource: a thumbnail image, or a count of objects in a collection. Rather than have the client make an additional REST request, it's better to prefetch some of this information for the client, and include it with the link.

There's some other stuff peripherally related to links:

The application needs to handle the idea of a changed URL, so whenever a resource is relocated, a 3** status code is returned, with the new location. This is the developer's responsibility, and would be implemented in the router.

If a link to an outside resource changes, the catalog of links should be updated.

If a link to an outside resource requires a credential, perhaps some metadata can provide this credential. Perhaps it requires a proxy through the application.

I'm probably not going to implement this, but it's food for thought.