I’ve said recently that HTML is clunky for APIs, but I didn’t really give it much thought. Since then I have given it some more thought and that led to me creating an HTML variant of HAL to test the waters and find out exactly how awkward it is.

tl;dr - it’s actually not that bad. I’m almost convinced. I wrote some jQuery helpers and a stylesheet to turn it into something human-browsable. It all works ok.

The method

  • Ambiguity in a machine interface is bad. I had to establish some clear and unambiguous constraints.
  • I didn’t want any presentational info targetted at humans to muddy the machine interface, which means that surfacing the selectors in a web browser had to be done via the css3 content property.. I did have to resort to JS in a couple of places.
  • I wanted to produce valid HTML. Didn’t really manage this due to the use of rel=“self” upsetting the validator. I can live with that.

How It Looks

You can see here how it renders in a browser.

Here’s the markup (minus style and script tags):

Issues

There were a couple of road-blocks I ran up against here whilst trying to stick to purely html and css:

  • can’t present input names without (implemented JS shim)
  • can represent rel/class of links names as hyperlinks to docs (implemented JS shim)
  • can’t show headers for request to page (TODO: fix by overriding all links and forms to use xhr + pushState)

HAL-HTML jQuery API

I put together a rudimentary jQuery API for consuming this HAL-HTML stuff. It’s a bunch of helper methods that can be called on a resource element (there are top level methods on the jQuery object that default to the root resource [i.e. body tag]).

getLink('rel');
getProperty('name');
getResource('rel');
getControl('name');
fill_in('input_name', { with: 'value' });

They should be relatively self explanatory, I think the most interesting is the last function ‘fill_in’ which is meant to be called on a control element. It returns the control element so you can chain it, you end up with code that looks like this:

$.getControl('ht:make-reply').fill_in('content', { with: 'zomg awesome hypermedia client' }).submit();

The 'spec’

The below are the basic rules that describe how to express HAL with HTML.

Resources

There are two types of resource in a hal-html document:

  • Root Resource, target of request (represented as body element)
  • Embedded Resource, contained/in-line resources to save request (see Embedded Resources section below for how these are represented.)

Properties

Selector Pattern

{resource} > .properties > input[name="{property}"]

Examples

body > .properties > input[name="created_at"]
body > .embedded > .post > .properties > input[name="content"]

Links

Selector Pattern

{resource} > .links > a[rel~="{relation}"]

Examples

body > .links > a[rel~="author"]
body > .embedded > .post > .links > a[rel~="self"]

Embedded Resources

Selector Pattern

{resource} > .embedded > .{relation}

Examples

body > .embedded > .post

Form Controls

Selector Pattern

{resource} > .controls > form[name~="{control_name}"]

Examples

body > .controls > form[name~="make-reply"]

Conclusion

This was all relatively simple and, now that I’ve done it and thought about it some more, I’ve come to the conclusion that applying HAL’s information model to HTML results in a pretty clean generic interface for machines that you can easily build tooling around.

I’m still not sure using HTML for an API is a brilliant business descision right now though, it’s a bit too “out there” still. ;)