MicroTypes
Composability for HTTP APIs
Filippos Vasilakis
Web Engineer at Kollegorna
MicroTypes: Compsability for HTTP APIs
- Challenges on API evolvement
- MicroTypes
- 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
- come and talk to me :)
- @vasilakisfil
MicroTypes is part of the Introspected REST manifesto
MicroTypes: Composability for HTTP APIs
By Filippos Vasilakis
MicroTypes: Composability for HTTP APIs
- 2,336