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?
3 Answers 3
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.
Your going to hate(oas) this answer but my interpretation of the original idea would be:
<form method="get" action="products">
<input type="number" name="priceGreaterThan"/>
<input type="submit"/>
</form>
You have given full interpretable information on what to pass and how to pass it in Hypermedia format.
In fact before i get a million down votes let me back myself up with some Roy Fielding quotes:
A truly RESTful API looks like hypertext.
and
Think of it in terms of the Web. How many Web browsers are aware of the distinction between an online-banking resource and a Wiki resource? None of them. They don’t need to be aware of the resource types. What they need to be aware of is the potential state transitions — the links and forms — and what semantics/actions are implied by traversing those links.
and
the media type tells the client either what method to use (e.g., anchor implies GET) or how to determine the method to use (e.g., form element says to look in method attribute).
-
1Good answer: references to (json) media types with form support would make it stronger.VoiceOfUnreason– VoiceOfUnreason05/14/2018 19:52:58Commented May 14, 2018 at 19:52
-
or as RF is asked directly in the same blog post comments: "...I just want to know if there are any known media types besides HTML that is suitable for REST interfaces. As I see it, HTML is not ideal for an API intended to be used by a machine." Roy remains silent on this questionEwan– Ewan05/14/2018 20:04:38Commented May 14, 2018 at 20:04
-
oh wait, i tell a lie "...using microformats of HTML, RDF in N3 or XML, or even SVG..." RFEwan– Ewan05/14/2018 20:06:45Commented May 14, 2018 at 20:06
-
Hypertext =/=> HTML. See Roy Fielding's comment here : roy.gbiv.com/untangled/2008/… There are much more convenient media types than
text/html
to convey this, IMO.guillaume31– guillaume3105/15/2018 12:24:09Commented May 15, 2018 at 12:24 -
@guillaume31 I think that's the same page i am quoting from. I think it would be more accurate to say HTML is a form of hypertext. Other forms (allegedly) exist, but it seems hard to name any which are json based. presumably you can define you own media type ewans/json or whatever which has the equivalent of forms but in json rather than xmlEwan– Ewan05/15/2018 12:38:32Commented May 15, 2018 at 12:38
Other than the ones mentioned by Jason, Collection+JSONs Query Templates may be a good fit here though I'm not a huge fan of its verbosity.
Perhaps more elegantly, HAL uses URI templates to describe parameterized links:
{
"_links": {
"ea:find": {
"href": "/orders{?id}",
"templated": true
}
}
}