Search code examples
resthateoas

REST API - How to query for links discovery?


Suppose I have a RESTful HATEOAS API which has /posts endpoint which lists posts with a query shortcut /posts/new. How do I query the API to discover /posts/new?

My ideas:

1) Query /posts and get links from _links attribute (and the entities listed are necessary overhead):

GET /posts

{
  "docs": [
    ...
  ]
  "_links": {
    "new": { "rel": "posts", "href": "/posts/new" }
  }
}

2) Provide this in the API root together with list of resources:

GET /

{
  "resources": {
    "posts": {
      "_links": {
        "self": { "rel": "posts", "href": "/posts" }
        "new": { "rel": "posts", "href": "/posts/new" }
      }
    }
  }
}

3) I should not use the /posts/new query and instead use /posts and query params. However, if I change my server logic I would have to change client logic too and that would be serve-client coupling. For example:

  • New messages will be requested by client by somehow providing parameter timestamp > (today - 30)
  • I introduce draft property and change my idea that new are only the posts with timestamp > (today - 30) && draft = false
  • I have to change client to add drafts constraint

Note: posts is just an example I am asking in general.


Solution

  • In a REST architecture URIs should be discovered via their accompanying link-relation name. On interpreting your examples above as HAL the URI /post/new has a link-relation name of new. Link relation names provide semantics to URIs which allow clients to determine when to invoke these URIs. HAL is just one of a handful JSON-based media types that support HATEOAS. There are further media-types available that provide a similar job with slightly different syntax and capabilities.

    Upon receiving such a document a client would parse the message and build some context for the message containing the actual content including additional metadata like links and further embedded data. If it wants to retrieve the list of the most recent posts it basically needs to look up the key (link-relation name) that expresses the intent (new in your case) from the before-mentioned context in order to retrieve the assigned value (URI). How a client maintains this context is some implementation detail. It might build up a tree-map for easier lookup of "link-relation" keys and their values (URIs) or use some totally different approach.

    The knowledge what key to use needs to be present somehow. As link relations express certain semantics they need to be specified somewhere. This can happen in industry standards or media-type definitions. IANA maintains a list of standardized link-relation names and their semantics. On examining the list probably the most likely match according to your specification is current which is defined as

    Refers to a resource containing the most recent item(s) in a collection of resources.

    I'd therefore propose to change the link-relation name from new to current.