REST HATEOAS – Representing Links with Client-Defined Parameters

hateoasrest

I'm wondering how best to model in a HATEOAS based API links that allow the client to set parameters. E.g. imagine a search response that returns a list of producst and then refinements that can be performed on them:

{
    "results" : {
        ...
    }
    "refinements" : {
        "Size" : {
            "links" : {
               "extra small" : "/products?size=xs",
               "medium" : "/products?size=m"
            }
        }, 
        Price : {
            links: {
                "greater than" : "/products?priceGreaterThan=aValue",
                "less than" : "/products?priceLesshan=aValue",
                "between" : "/products?priceLesshan=aValue&priceGreaterThan=aValue"
            }
        }
    }
}

The size refinements seem straight forwards but the price refinements require the client to pass a value. How is this typically represented in a HATEOAS link?

Best Answer

I highly recommend that, when using hypermedia, you use a hypermedia enabled media type. There are many JSON based media types out there that support form-like interactions.

Here is an example using JSON Hyper-Schema. It behaves just like an HTML Form with method="get".


/product

HTTP/1.1 200 OK
Content-Type: application/json
Link: </schema/product-list>; rel="describedby"

{
  results: [ ... ]
}

/schema/product-list

HTTP/1.1 200 OK
Content-Type: application/schema+json

{
  "$schema": "http://json-schema.org/draft-04/hyper-schema#",
  "links" : [
    {
      "rel": "search",
      "href": "/products",
      "schema": {
        "type": "object",
        "properties": {
          "size": { "enum": ["xs", "m"] },
          "priceGreaterThan": { "type": "number" },
          "priceLessThan": { "type": "number" }
        }
      }
    }
  ]
}

A generic client can build all of the links from your example and more with this schema. Other examples of media types with similar capabilities are Siren, Hydra, and of course HTML.

Related Topic