MicroTypes

Composability for HTTP APIs

Filippos Vasilakis

Web Engineer at Kollegorna

MicroTypes: Compsability for HTTP APIs

  1. Challenges on API evolvement
  2. MicroTypes
  3. Reactive negotiation

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

Filippos Vasilakis | @vasilakisfil

MicroTypes

Composability for HTTP APIs

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Earliest online HTML document

<title>Hypertext Links</title>
<h1>Links and Anchors</h1>
A link is the connection between one piece of
<a href=WhatIs.html>hypertext</a> and another.

Last-Modified: Tue, 13 Nov 1990 15:17:00 GMT

Page today is functional and link is still valid

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

Networked Services

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis

  • We need to think about evolvability
    • introduce changes without breaking clients
    • evolve and drive umanned clients

How do we achieve evolvability?

  • client asks for representations that it understands
    • self-descriptive content
  • server tries to satisfy client

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Client

URL

API

JSONAPI

HAL

GraphQL

1. requests the resource

2. returns the most appropriate representation

Accept:application/vnd.api+json
Content-Type:application/vnd.api+json

Proactive negotiation

also called hint-based or server-driven

SIREN

content taken by Mozilla's Developer Network, adapted

Collection+JSON

Accept:application/vnd.api+json, application/hal+json; q=0.9,
application/vnd.siren+json; q=0.8
Accept:application/vnd.api+json, application/hal+json; q=0.9

JSONAPI

HAL

SIREN

JSONAPI

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

JSONAPI

HAL

GraphQL

SIREN

Collection+JSON

Media Types

Content-Type:application/vnd.api+json

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

Accept:application/vnd.api+json, application/hal+json; q=0.9,
application/vnd.siren+json; q=0.8

Media Types

RFC 2046 & RFC 6838

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

  • response format & structure
  • request format & structure
  • Hypermedia (HATEOAS)
  • Capabilities
    • pagination, sorting
    • filter queries
    • aggregation queries

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

A Media Type specifies all our APIs semantics

For example:

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      // ... this article's attributes
    },
    "relationships": {
      // ... this article's relationships
    }
  }
}
{
  "meta": {
    "copyright": "Copyright 2015 Example Corp.",
    "authors": [
      "Yehuda Katz",
      "Steve Klabnik",
      "Dan Gebhardt",
      "Tyler Kellen"
    ]
  },
  "data": {
    // ...
  }
}
GET /articles/1?include=author,comments.author
GET /articles?include=author&fields[articles]=title,body&fields[people]=name
GET /articles?sort=-created,title
  "links": {
    "self": "http://example.com/articles?page[number]=3&page[size]=1",
    "first": "http://example.com/articles?page[number]=1&page[size]=1",
    "prev": "http://example.com/articles?page[number]=2&page[size]=1",
    "next": "http://example.com/articles?page[number]=4&page[size]=1",
    "last": "http://example.com/articles?page[number]=13&page[size]=1"
  }
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/vnd.api+json

{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/first-name" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}

JSONAPI Media Type

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "links": {
      "self": "http://example.com/articles/1"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      }
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }]
}
application/vnd.api+json

APIs today are quite powerful (and complex)

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis ; @vasilakisfil

doesn't always feel right :(

Moving fast and painlessly is crucial

(painlessly for our clients as well)

We need to evolve  our API ?

(= add new features and capabilities)

No problem! Just add it to the documentation.

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

The formal way: just create a new Media Type.

The formal way: just create a new Media Type.

No problem! Just add it to the documentation.

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/first-name" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}
{
  "title": "Invalid Attribute.",
  "details": "First name must contain at least three characters.",
  "status": 422
}

Evolving our error messages

RFC 7807

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

JSONAPI

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

  "links": {
    "self": "http://example.com/articles?page=3&per_page=10",
    "first": "http://example.com/articles?page=1&per_page=10",
    "prev": "http://example.com/articles?page=2&per_page=10",
    "next": "http://example.com/articles?page=4&per_page=10",
    "last": "http://example.com/articles?page=13&per_page=10"
  }
  "links": {
    "self": "http://example.com/articles?page={page}&per_page={per_page}",
    "first": "http://example.com/articles?page={page}&per_page={per_page}",
    "prev": "http://example.com/articles?page={page}&per_page={per_page}",
    "next": "http://example.com/articles?page={page}&per_page={per_page}",
    "last": "http://example.com/articles?page={page}&per_page={per_page}"
  }
Link: <http://example.com/articles?page=3&per_page=10>; rel="self",
  <http://example.com/articles?page=1&per_page=10>; rel="first",
  <http://example.com/articles?page=2&per_page=10>; rel="prev",
  <http://example.com/articles?page=4&per_page=10>; rel="next",
  <http://example.com/articles?page=13&per_page=10>; rel="last"

Evolving our pagination

RFC 5988

RFC 6570

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

What if we need

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

  • different error messages
    • per platform
    • RFC 7807 Problem Details for HTTP APIs
  • Different pagination
    • pagination on Link header
    • URI templates
  • different querying language
    • exploit the power of GraphQL
  • Different hypermedia
    • URI templates in links and actions
    • Semantic links
  • More advanced:
    • Deprecations
    • Server Side Events
      • ​real time updates

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis ; @vasilakisfil

A system intending to be as long-lived as the Web must be prepared for change.

Roy Fielding

If you want to move fast,

you should build a change-first API.

The best software architecture “knows” what changes often and makes that easy.

Paul Clements

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

Media Types are monoliths

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

  • evolve (bad) parts of our API
  • negotiate parts of the API functionality
  • support of different classes of clients

Solution ?

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

also called Features*

small reusable modules that compose a Media Type and facilitate the evolvability and extensibility of our API.

Introspected REST manifesto

An interface feature is a part of an interface that identifies, describes, and affords a certain kind of interaction across Web APIs.

Ruben Verborgh, Michel Dumontier, A Web API ecosystem through feature-based reuse. CoRR, 2016

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

API

functionalities

monolith interface

API-specific client

API

functionalities

modular interface features

MicroTypes-aware client

defines

implemented as

Top →Down

Bottom →Up

A different approach

defines

provides

content taken by Ruben Verborgh, Michel Dumontier, A Web API ecosystem through feature-based reuse. CoRR, 2016, adapted

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

building blocks

a reusable

self-describing

module

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Parent Media Type

JSONAPI Pagination

Strategy

Link Header Pagination Strategy

URI Templates Pagination Strategy

 Problem Details for HTTP APIs
(RFC 7807)

JSONAPI
error messages

JSONAPI
Resource(s)/Fields Querying

GraphQL Resource/Fields Querying

Forms and Actions

spec

JSON-LD

main functionalities

response & request format

message format

MicroTypes support

Let's not build monoliths

API Version 1.0

API Version 1.1

API Version 1.2

API Version 1.3

API Version 1.4

API Version 1.5

API Version 1.6

API Version 2.0

Deprecated (!)

Removed

let's not re-invent the wheel either

Deprecations

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Client

URL

API

1. requests the resource

2. returns the most appropriate representation

MicroTypes & Proactive negotiation

JSONAPI Pagination

Strategy

Link Header Pagination Strategy

URI Templates Pagination Strategy

 Problem Details for HTTP APIs
(RFC 7807)

JSONAPI
error messages

JSONAPI
Resource(s)/Fields Querying

GraphQL Resource/Fields Querying

Forms and Actions

spec

Parent Media Type

(JSONAPI)

Parent Media Type

(HAL)

Accept: application/vnd.api+json; pagination=jsonapi;
Content-Type: application/vnd.api+json; pagination=jsonapi; querying=jsonapi; errors=rfc7807

some content taken by Mozilla's Developer Network, adapted

Accept: application/vnd.api+json;
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi; errors=rfc7807; errors=jsonapi,
    application/vnd.hal+json; pagination=jsonapi; querying=jsonapi;
errors=jsonapi; q=0.9
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi;
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi; errors=rfc7807;
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi; errors=rfc7807; errors=jsonapi
Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi; errors=rfc7807; errors=jsonapi,
    application/vnd.hal+json; pagination=jsonapi; querying=jsonapi;
errors=jsonapi; q=0.9,
application/vnd.hal+json

Media Type parameters

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

MicroTypes & Proactive negotiation

Until then, Media Type parameters works fine :)

What about RFC 6906 (The 'profile' Link Relation Type) ?

  • fails to advocate towards reusable profiles
  • fails to provide preference semantics for proper negotiation

(!) New IETF draft: Negotiating Profiles in HTTP

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis ; @vasilakisfil

MicroTypes

Composability for HTTP APIs

  • Break down monolithic Media Types into small reusable modules

What about MicroTypes discovery ?

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Client

URL

API

1. requests the resource

2. returns the most appropriate representation

Proactive negotiation

also called hint-based or server-driven

JSONAPI Pagination

Strategy

Link Header Pagination Strategy

URI Templates Pagination Strategy

 Problem Details for HTTP APIs
(RFC 7807)

JSONAPI
error messages

JSONAPI
Resource(s)/Fields Querying

GraphQL Resource/Fields Querying

Forms and Actions

spec

Parent Media Type

(JSONAPI)

Parent Media Type

(HAL)

Content-Type: application/vnd.api+json; pagination=jsonapi; querying=jsonapi; errors=rfc7807

some content taken by Mozilla's Developer Network, adapted

Accept: application/vnd.api+json; pagination=jsonapi; querying=graphql;
querying=jsonapi; errors=rfc7807; errors=jsonapi,
    application/vnd.hal+json; pagination=jsonapi; querying=jsonapi;
errors=jsonapi; q=0.9,
application/vnd.hal+json

How can clients know?

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

 RFC 7231 notes that proactive negotiation has some serious disadvantages

  • It is impossible for the server to accurately determine what might be “best” for any given user
  • Having the user agent describe its capabilities in every request can be both very inefficient a potential risk to the user’s privacy
  • It complicates the implementation

With reactive negotiation (a.k.a., agent-driven negotiation), selection of the best response representation (regardless of the status code) is performed by the user agent after receiving an initial response from the origin server that contains a list of resources for alternative representations

RFC 7231

available since RFC 2068, published in 1997

not a single API uses it (!)

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Client

URL

API

3. request specific representation

Reactive negotiation

also called agent-driven negotiation

JSONAPI Pagination

Strategy

Link Header Pagination Strategy

URI Templates Pagination Strategy

 Problem Details for HTTP APIs
(RFC 7807)

JSONAPI
error messages

JSONAPI
Resource(s)/Fields Querying

GraphQL Resource/Fields Querying

Forms and Actions

spec

JSON-LD

Parent Media Type

(JSONAPI)

Parent Media Type

(HAL)

2. show available options

1. requests for available

4. return specified representation

Accept: application/vnd.api+json; pagination=uri-templates;
  querying=graphql; querying=jsonapi; errors=jsonapi;
  errors=rfc7807,
  application/vnd.hal+json; pagination=uri-templates;
  querying=jsonapi; querying=jsonapi; q=0.9
Content-Type: application/vnd.api+json; pagination=jsonapi; querying=jsonapi; errors=rfc7807

some content taken by Mozilla's Developer Network, adapted

MicroTypes

How?

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Reactive negotiation

There is an HTTP method for that: 

HTTP OPTIONS
The OPTIONS method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action.

RFC 7231

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis | @vasilakisfil

Reactive negotiation

OPTIONS /api HTTP/1.1

{
  "micro-types": {
    "application/mt.pagination+jsonapi",
    "application/mt.pagination+uri-templates",
    "application/mt.pagination+web-linking",
    "application/mt.querying+jsonapi",
    "application/mt.querying+graphql",
    "application/mt.errors+jsonapi",
    "application/mt.errors+rfc7807",
    "application/mt.linking+json-ld"
    "application/mt.actions+siren"
  }
}

also called agent-driven negotiation

Link: <https://www.example.com/api/users?microtype=pagination+jsonapi>;
     rel="microtype"; name="application/mt.pagination+jsonapi",
      <https://www.example.com/api/users?microtype=pagination+uri-templates>;
     rel="microtype"; name="application/mt.pagination+uri-templates",
      <https://www.example.com/api/users?microtype=pagination+web-linking>;
     rel="microtype"; name="application/mt.pagination+web-linking",
      <https://www.example.com/api/users?microtype=querying+jsonapi>;
     rel="microtype"; name="application/mt.querying+jsonapi",
      <https://www.example.com/api/users?microtype=querying+graphql>;
     rel="microtype"; name="application/mt.querying+graphql",
      <https://www.example.com/api/users?microtype=errors+jsonapi>;
     rel="microtype"; name="application/mt.errors+jsonapi",
      <https://www.example.com/api/users?microtype=errors+rfc7807">;
     rel="microtype"; name="application/mt.errors+rfc7807"",
      <https://www.example.com/api/users?microtype=linking+json-ld>;
     rel="microtype"; name="application/mt.linking+json-ld",
      <https://www.example.com/api/users?microtype=linking+json-ld>;
     rel="microtype"; name="application/mt.actions+siren"

HTTP Body

RFC 5988

The method of discovery can be yet another

MicroType

through Proactive Negotiation

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis ; @vasilakisfil

MicroTypes

Composability for HTTP APIs

  • Break down monolithic Media Types into small reusable modules
  • Discovery of available MicroTypes through Reactive Negotiation

What else can we do with MicroTypes & Reactive negotiation?

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

MicroTypes: Compsability for HTTP APIs

Filippos Vasilakis ; @vasilakisfil

Thank you!

Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery

For feedback, comments, questions etc

MicroTypes is part of the Introspected REST manifesto

MicroTypes: Composability for HTTP APIs

By Filippos Vasilakis

MicroTypes: Composability for HTTP APIs

  • 2,185