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,213