From Media Type to MicroTypes

Filippos Vasilakis

Web Engineer at Kollegorna

and Introspected REST

Media Types

RFC 2046 & RFC 6838

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

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

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

A Media Type specifies all our APIs semantics

For example:

From Media Types to MicroTypes

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 | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis ; @vasilakisfil

Each Media Type define same concepts in a different way

  • Links
  • Pagination
  • Actions
  • Querying
  • Embedded resources
  • Errors
  • Metadata

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis ; @vasilakisfil

doesn't always feel right :(

Need to introduce a small semenatic change in our API ?

No problem! Just add it to the documentation.

The formal way: just create a new Media Type.

No problem! Just add it to the documentation.

Use RFC 6906 (The 'profile' Link Relation Type)

it should never ever alter the semantics Media Type in use

Use RFC 6906 (The 'profile' Link Relation Type)

non self-descriptive content :(

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

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 | Media Types | MicroTypes |MicroTypes in HTTP

What if we need

From Media Types to MicroTypes

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 | Media Types | MicroTypes |MicroTypes in HTTP

Media Types are monoliths

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

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

Solution ?

We cannot

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

also called Features*

small, isolated, reusable, configurable modules that are negotiable and discoverable. MicroTypes compose a Media Type to facilitate the evolvability and extensibility of our API.

microtypes.info

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 | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes

Small

  • small in scope
  • defines only a specific functionality

Isolated

  • single responsibility
  • no dependencies on other MicroTypes
    • dependencies on RFCs and other standards is perfectly valid

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Reusable

  • not coupled to a specific Media Type
  • solves the problem for broader use
    • takes care of edge cases

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

If you use a cool pattern in your API consider it wrapping it in a MicroType

MicroTypes

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Configurable

  • people are different, let's embrace it
  • let API designer tailor MicroType to her needs
  • maximizes reusability

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Configurable

A pagination MicroType

  • location of pagination object inside document
    • JSON Pointer
  • per_page, page and offset query parameter names
    • schema.org, JSON-LD etc
  • max per_page number (e.g. 50 items per page)
    • JSON Schema ?

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Negotiable

  • let the client decide the set of MicroTypes based on its capabilities and current state

Discoverable

  • inform the client for all available MicroTypes

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

  • Small
  • Isolated
  • Reusable
  • Configurable
  • Negotiable
  • Discoverable

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

Modules!

API

functionalities

monolith interface

API-specific client

API

functionalities

modular interface features

MicroTypes-aware client

defines

implemented as

Top →Down

Bottom →Up

Small, Isolated, Reusable

defines

provides

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

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

building blocks

a reusable

self-describing

module

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

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

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 build monoliths, let's not re-invent the wheel either

Deprecations

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

Small, Isolated, Reusable

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Configurable

Configuration link(s) can be defined:

  • by the parent Media Type
    • OPTIONS /api/pagination
  • by the MicroType itself
    • GET /api/_microtypes/pagination
  • a combination

API designer should always be able to decide

ideal

From the client perspective, configuration is called introspection

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Client

URL

API

1. requests the resource

2. returns the most appropriate representation

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

Negotiable

also called hint-based or server-driven

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Client

URL

API

1. requests the resource

2. returns the most appropriate representation

Discovery

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 | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

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 | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Client

URL

API

3. request specific representation

Discovery 

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

Media Types + MicroTypes

How?

through reactive negotiation

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

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

Discovery 

through reactive negotiation

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

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"
  }
}
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

Discovery 

through reactive negotiation

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

MicroTypes in HTTP

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

  • Small
  • Isolated
  • Reusable
  • Configurable
  • Negotiable
  • Discoverable

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

Modules!

MicroTypes can lead to sustainable API designs

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

  • Introduce changes in a standard way
  • Composable Media Types
  • Discovery and introspection for things that otherwise would go to documentation..

Thank you!

From Media Types to MicroTypes

Filippos Vasilakis | @vasilakisfil

Introduction | Media Types | MicroTypes |MicroTypes in HTTP

From Media Type to MicroTypes

and Introspected REST

From Media Types to MicroTypes

By Filippos Vasilakis

From Media Types to MicroTypes

From Media Types to MicroTypes and Introspected REST

  • 2,191