title | date | location | geo | tags | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Ketting 1.0 release. |
2018-03-25 23:58:57 -0700 |
New Montgomery St, San Francisco, CA, US |
|
|
Since 2016 I've been working on a javascript library to make it easier to work with HAL REST services. Yesterday I realized I implemented all the features I wanted for a 1.0 release, and also that I never talked about it on this blog.
So this evening I released 1.0, and also share some information about it here. It's been almost a year since I blogged! Really gotta get back on this horse.
Nearly 2 years ago we implemented a new API at a company I worked at. We chose to go the REST/hypermedia/HATEOAS route and use HAL as the primary format.
I had a drive to try and see what a good client for this would look like, so I decided to write my own in my free time.
This client is written in Javacript, works in node.js and in browsers. We use it as a real client, but also doing black-box testing of API's.
- It parses HAL
_links
and provides a convenient API for following links. - Uses the Fetch API for HTTP requests and is heavily promise-based.
- Automatically parsed items in
_embedded
and stores them in a cache. The nice thing about this is that if a server chooses to embed certain items, the client will automatically adapt and 'upgrade' to take advantage of this, resulting in less requests. - Recognizes
application/problem+json
responses and automatically converts them to exceptions. - Supports Basic auth, Bearer tokens.
- Also implements some of OAuth2, including the
password
,client_credentials
grant types and will automatically refresh expired access tokens if a refresh token was provided. - Supports HTTP
Link:
headers and merges them in with HAL links, allowing you to follow links on non-HAL or non-JSON resources. - Similarly, if given a HTML document it will extract all
<link>
and<a>
tags withrel=
attributes.
Generally with REST you'll want to 'discover' urls based on link relationships, and not hardcode them. This is the main focus of the API.
The following sample does the following:
- Create a new client and specify the 'bookmark url' of the API to
https://api.example.org
. - Find a collection of articles using
rel="articleCollection"
. - Grab the first article in that collection (generally items in a collection
use
rel="item"
. See RFC6573). - Do a
GET
request on the article, and afterwards follow therel="author"
link. - Lastly, change the name of the author by doing a
PUT
request.
const ketting = new Ketting('https://api.example.org');
// Ketting uses a special promise that has a `follow` function so it can be
// chained to do multiple hops.
const articleResource = await ketting.follow('articleCollection').follow('item');
const articleBody = await article.get();
const authorResource = await articleResource.follow('author');
const authorBody = await authorResource.get();
authorBody.name = 'Evert Pot';
await authorResource.put(authorBody);
A few notes:
- Any of these hops could have been HTML documents, HAL documents or any
resource with a
Link
header. Only the last one (author) really had to be JSON, because we're parsing it and changing it. - If any of the followed links appeared in
_embedded
, they're stored in a local cache and those HTTP requests would have been skipped. - Ketting will wait till the last possible moment to do a HTTP request. Sometimes it's a bit surprising when the actual HTTP request happens. following a link generally does not.
Anyway, I hope this is interesting to other folks! Special thanks to @mhum for his significant contributions.
Some things that might happen for a 2.0 version: