Search code examples
hateoas

HATEOAS with multiple pages


Is there a rule to define a sequential list of links using HATEOAS?

It is easy to add self, next and previous links to a HATEOAS-based response. Below is a sample response:

{ 
  links : [{
            rel : "next",
            href : "http://localhost:8080/persons?page=1&size=20"
          }], 
  content : [{
     id: "",
     name: "",
     lastname: "",
     age: 0
  }],
  pageMetadata : { 
    size : 20, 
    totalElements : 30, 
    totalPages : 2, 
    number : 0
  } 
};

So, pagination with next and previous links is not difficult but I couldn't figure out how it is possible to access for example 10th page directly, for example using a select element (let's assume there are more than 10 pages). Should I add all the links to the response as, for example, page1, page2, page3, etc? Of course I know the format of the request so I could just create the appropriate query but that seems kind of wrong because the whole point seems to be not relying on the actual link of the service. I am not an expert on this issue and I couldn't find an answer in this site or from Google. Thanks in advance.


Solution

  • The common solution is to use URI templates. Specifically, section 3.2.8 regarding Form-Style Query Expansion.

    Assuming both page and size are optional, you would construct your link URI template as localhost:8080/persons{?page,size}.

    URI templates do not define which values are acceptable; there's no mechanism for restricting page or size to numeric values. As such, you should include this template in addition to your existing next/prev links. I'm not exactly sure which link relation best describes such a resource, but "collection" doesn't seem too far off.

    In order to use URI templates, you'll need a library in whichever languages will be producing/consuming the template. A quick search produced a list of libraries in various languages which you may find helpful.

    Lastly, depending on your hypermedia format you may need to specify a templated URI as such. For example, HAL+JSON uses a boolean templated property.

    {
        "_links": {
            "collection": {
                "href":      "/persons{?page,size}",
                "templated": true
            }
        }
    }