Search code examples
restrestful-architectureapi-designrestful-urlhateoas

REST Hateos: How to make sure that client enters REST application through a simple fixed URL?


We want to create a screen on multiple clients that shows "5 best selling product", "5 recently added product" and "5 product with great offers". All these would be shown as carousel.

We want to create Restful APIs for these. We have created following APIs:

  1. /api/bestsellingproduct/
  2. /api/recentlyaddedproduct/
  3. /api/greatofferproduct/

Currently, every client i.e. desktop, mobile, android, ios has hard-coded these URIs. I am worried if we tomorrow change these URLs, it would be cumbersome and also REST suggests that "A REST client enters a REST application through a simple fixed URL. (Ref: https://en.wikipedia.org/wiki/HATEOAS)"

Can someone suggest how I can ensure that all clients enter application through simple fixed URL in this case?


Solution

  • In HATEOAS URIs are discoverable (and not documented) so that they can be changed. That is, unless they are the very entry points into your system (Cool URIs, the only ones that can be hard-coded by clients) - and you shouldn't have too many of those if you want the ability to evolve the rest of your system's URI structure in the future. This is in fact one of the most useful features of REST.

    For the remaining non-Cool URIs, they can be changed over time, and your API documentation should spell out the fact that they should be discovered at runtime through hypermedia traversal.

    Looking at the Richardson's Maturity Model (level 3), this would be where links come into play. For example, from the top level, say /api/version(/1), you would discover there's a link to the groups. Here's how this could look in a tool like HAL Browser:

    Root:

    {
      "_links": {
        "self": {
          "href": "/api/root"
        },
        "api:bestsellingproduct": {
          "href": "http://apiname:port/api/bestsellingproduct"
        },
        "api:recentlyaddedproduct": {
          "href": "http://apiname:port/api/recentlyaddedproduct"
        },
        "api:greatofferproduct": {
          "href": "http://apiname:port/api/greatofferproduct")
        }
      }
    }
    

    The advantage here would be that the client would only need to know the relationship (link) name (well obviously besides the resource structure/properties), while the server would be mostly free to alter the relationship (and resource) url.

    You could even embed them to be returned in the same root api call:

    {
      "_embedded": {
        "bestsellingproduct": [
            {               
                "id": "1",
                "name": "prod test"
            },
            {               
                "id": "2",
                "name": "prod test 2"
            }
        ],
        "recentlyaddedproduct": [
            {               
                "id": "3",
                "name": "prod test 3"
            },
            {               
                "id": "5",
                "name": "prod test 5"
            }
        ]
    }