Filippos Vasilakis
Web Engineer at Kollegorna
and Introspected REST
RFC 2046 & RFC 6838
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
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."
}
]
}
{
"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
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis ; @vasilakisfil
doesn't always feel right :(
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"
RFC 5988
RFC 6570
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Solution ?
We cannot
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
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
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
If you use a cool pattern in your API consider it wrapping it in a MicroType
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
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
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
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Configuration link(s) can be defined:
OPTIONS /api/pagination
GET /api/_microtypes/pagination
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
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
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
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
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
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
through reactive negotiation
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
Modules!
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
From Media Types to MicroTypes
Filippos Vasilakis | @vasilakisfil
Introduction | Media Types | MicroTypes |MicroTypes in HTTP
and Introspected REST