> ## Content Index
> Fetch the complete content index at: https://apisyouwonthate.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Easy to Follow Hypermedia Controls with Ketting
- URL: https://apisyouwonthate.com/blog/ketting-v5-hypermedia-controls/
- Published: 2019-11-22T12:00:00.000Z
- Updated: 2023-03-24T12:23:09.000Z
- Author: Evert Pot
- Tags: #Import 2023-03-24 12:19

Hi! My name is Evert, and for a while now I've been working on a project  
called [Ketting](https://github.com/evert/ketting?ref=apisyouwonthate.com), which is a generic Hypermedia/HATEOAS client for  
Javascript. I just released version 5.0, and thought it might be interesting  
to share the new features that have been added since earlier this year.

These are the highlights.

## Support For Siren

Ketting now features support for [Siren](https://github.com/kevinswiber/siren?ref=apisyouwonthate.com). This means that the client now  
understands this format and can transparently traverse Siren links.

```typescript
const newRes = await res
  .follow('author') // this could be a HTML5 link
  .follow('me') // This might be a Siren link 

```

Ketting now has support for HTML, [HAL](https://tools.ietf.org/html/draft-kelly-json-hal?ref=apisyouwonthate.com), [JSON:API](https://jsonapi.org/?ref=apisyouwonthate.com), [HTTP Link headers](https://tools.ietf.org/html/rfc8288?ref=apisyouwonthate.com) and [Siren](https://github.com/kevinswiber/siren?ref=apisyouwonthate.com) links. [Collection+JSON](http://amundsen.com/media-types/collection/format/?ref=apisyouwonthate.com) is also in the works  
and will likely follow soon after in a point release.

## Advanced Follow Features

Usually if you want to fetch a collection of things, you might do it using  
this API:

```typescript
const articles = await res
  .follow('article-collection')
  .followAll('item') // This might be a list of links to each individual article

```

In HTTP/1.1 style APIs, it was common to actually embed the responses of  
every 'item' in a collection using for example's HAL `_embedded` property or  
JSON:API's `included`.

This is kind of an [anti-pattern](https://apisyouwonthate.com/blog/lets-stop-building-apis-around-a-network-hack), but a necessary evil because HTTP/1.1  
requests have a large amount of overhead.

Ketting will take all the items in `_embedded` and store the items in  
its cache, so that future `GET` requests are not needed.

In HTTP/2 APIs requests are less expensive, and it's often desirable to make  
more smaller HTTP requests and responses.

To help with this, the follow/followAll have these new features:

### Prefetching

```typescript
const newRes = await res
  .follow('article-collection')
  .followAll('item')
  .preFetch();

```

The `preFetch()` on followAll will cause Ketting to follow every `item` link,  
do a `GET` request for each in parallel in the background and store it in its  
cache.

We did some testing with an internal application and were able to prefetch an  
entire collection of 1700 items (so 1700 `GET` requests) in about 7 seconds.

While this could benefit from some paging, it was great to see how fast HTTP/2  
servers can be.

### Sending Prefer-Push

Very similarly, there's also a chainable `preferPush()` on `follow` /  
`followAll`:

```typescript
const newRes = await res
  .follow('article-collection')
  .followAll('item')
  .preferPush();

```

This will cause Ketting to send a [Prefer-Push](https://tools.ietf.org/html/draft-pot-prefer-push?ref=apisyouwonthate.com) header when fetching the  
articles collection:

```
GET /articles HTTP/2
Prefer-Push: item

```

If a server supports this header, they can optimize future requests by sending  
HTTP/2 pushes for each linked item.

## Support For `rel="invalidates"`

Ketting now understands the 'invalidates' link relationship from  
[draft-nottingham-linked-cache-inv](https://tools.ietf.org/html/draft-nottingham-linked-cache-inv-04?ref=apisyouwonthate.com).

A use-case for this is that a client might do a `POST` request on some  
resource, and the result of this resource causes other cached responds  
to invalidate.

This is handy, because an operation on one resource can alter the state of  
other, unrelated resources. Using this HTTP header, a server can tell a  
client which resources those are and control invalidation.

## New OAuth2 Library

Older versions relied on the [client-oauth2](https://www.npmjs.com/package/client-oauth2?ref=apisyouwonthate.com) for everything OAuth2, but this  
library is pretty bulky when WebPacked. This has since been changed over to  
[fetch-mw-oauth2](https://evertpot.com/fetch-mw-oauth2/?ref=apisyouwonthate.com), which is a library that wraps `fetch()` as a middleware  
and decorates it with OAuth2 features.

This caused the final Ketting Webpack distribution to drop over 30KB. While  
making this change, support for OAuth2 `authorization_code` was also added.

## Per-Domain Authentication

One of the nice advantages of using a hypermedia-style API, is that if multiple  
APIs support links, one way to integrate these APIs is simply by pointing links  
from one API to another.

A real life example was that one of our APIs needed some integration with the  
Github REST api, which uses HTTP Link headers for some stuff.

Our API could simply point to Github endpoints and the client was able to just  
traverse the graph and didn't have to be aware that some endpoints were served  
by Github.

However, our API and Github's each have their own authentication mechanisms.  
In previous Ketting versions authentication could only be set up once globally,  
causing the same credentials to be sent everywhere.

With the new authentication layer, it's possible to set Ketting up to use  
different authentication mechanisms based on the specific domains you're  
accessing, including wildcards.

```typescript
const ketting = new Ketting(bookmark, {
  match: {
    '*.github.com': {
       auth: {type: 'oauth2', /*...*/ }
    },
    'api.example': {
       auth: {type: 'basic', /*...*/ }
    },
  }
});

```

## Typescript Improvements

It's now possible to add Typescript annotations to various Ketting methods.

Consider the following example

```typescript
type Article = {
  title: string,
  body: string
};

const itemRes = await res1.follow<Article>('item');

```

This tells Typescript that the result of this `follow()` function is actually  
a `Resource<Article>`.

If a user later calls:

```typescript
const body = await itemRes.get();

```

body will now automatically have the `Article` type.  
Similarly, `item.put()` will also now require a parameter of type `Article`.

There's many more examples of this, which you can read on my [previous post](https://evertpot.com/ketting-generics/?ref=apisyouwonthate.com)  
on this subject.

## 201 And 205 Responses On POST

If a user calls `.post()` and the response to the HTTP POST request was a  
[201 Created](https://evertpot.com/http/201-created?ref=apisyouwonthate.com) and a `Location` header, it would automatically return a  
new resource.

```typescript
const newArticle = await articlesCollection.post(newArticle);

```

Now, when a server returns a HTTP [205 Reset Content](https://evertpot.com/http/201-created?ref=apisyouwonthate.com), the `post()`  
function will return the resource itself (`this`).

This is a small change that I hope is useful for APIs with strong hypermedia  
controls and folks that want to create clients that heavily rely on the entire  
application state being managed by the server.

## Conclusion

I hope you like the changes. My goal is to create the ultimate client for  
Hypermedia APIs, and I feel these are some good steps in that direction.

If you're an existing user, I would be very curious to hear what's currently  
painful and help adjust the future of this project.

If you're a new user and interested in using it, check out the  
[Github project](https://github.com/evert/ketting?ref=apisyouwonthate.com) and [documentation](https://github.com/evert/ketting/wiki?ref=apisyouwonthate.com) (The latter of which also got a  
big overhaul).