Composability for HTTP APIs
Filippos Vasilakis
Web Engineer at Kollegorna
MicroTypes: Compsability for HTTP APIs
Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery
Filippos Vasilakis | @vasilakisfil
Composability for HTTP APIs
MicroTypes: Compsability for HTTP APIs
Filippos Vasilakis | @vasilakisfil
<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
MicroTypes: Compsability for HTTP APIs
Filippos Vasilakis
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
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
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
RFC 2046 & RFC 6838
MicroTypes: Compsability for HTTP APIs
Filippos Vasilakis | @vasilakisfil
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."
}
]
}
{
"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
}
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"
RFC 5988
RFC 6570
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
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
MicroTypes: Compsability for HTTP APIs
Filippos Vasilakis | @vasilakisfil
Solution ?
Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery
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
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
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
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
Until then, Media Type parameters works fine :)
What about RFC 6906 (The 'profile' Link Relation Type) ?
(!) 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
Composability for HTTP APIs
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
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
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
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
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
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
Composability for HTTP APIs
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
Introduction | Content Negotiation | Media Types | MicroTypes | Reactive Negotiation & MicroTypes Discovery
For feedback, comments, questions etc
MicroTypes is part of the Introspected REST manifesto