46
Web APIs Alexandre Bertails, Pellucid Analytics @bertails 1 / 46

One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Embed Size (px)

DESCRIPTION

Un simple site Web ne suffit plus : si je veux que les machines puissent comprendre et interagir avec mes données et pas seulement des pages HTML, je dois exposer une Web API. Or les styles, architectures et buzzwords sont variés (Web services, REST, hypermedia et maintenant HATEOAS, etc.) et les religions sont légion. Il a fallu de longues années pour que l’industrie et la communauté Web voient émerger de bonnes pratiques. L’heure est maintenant à la consolidation. Cette présentation se veut une rétrospective sur l’évolution des Web APIs et plus généralement des données sur le Web. Je ferai une revue de l’état de l’art, illustrée par des exemples concrets et des conseils pratiques. Le speaker : Alexandre est expert Linked Data à Pellucid Analytics. Auparavant au W3C. Code principalement en Scala et est intéressé par le Web, les données et les questions d’anonymat/vie privée sur le Web.

Citation preview

Page 1: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Web APIsAlexandre Bertails, Pellucid Analytics

@bertails

1 / 46

Page 2: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Web APIsWho are the users of my API?

What do they do with it?

How will they interact with it?

2 / 46

Page 3: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Web APIsWho are the users of my API?

What do they do with it?

How will they interact with it?

REST

hypermedia

HATEOAS

3 / 46

Page 4: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

HTTP, back to the basicsresources

representations

semantics

4 / 46

Page 5: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

HTTP interactions$ HEAD https://data.example.com/company/Content-Type: application/json

a media type specification sets out

formats

processing model

hypermedia controls

for its representation

5 / 46

Page 6: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

media typeContent-Type and Media Type as defined in HTTPBIS

HTTP uses Internet Media Types [RFC2046] in the Content-Type(Section 3.1.1.5) [...] header fields in order to provide open andextensible data typing [...]. Media types define both a data format andvarious processing models.

6 / 46

Page 7: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

IANA registry for media typesIANA registry for Media Types

Name Template Referencejson application/json [RFC7158]

7 / 46

Page 8: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

JSONThe JavaScript Object Notation (JSON) Data Interchange Format [RFC7159]

JSON can represent four primitive types (strings, numbers, booleans,and null) and two structured types (objects and arrays).

8 / 46

Page 9: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

JSONThe JavaScript Object Notation (JSON) Data Interchange Format [RFC7159]

JSON can represent four primitive types (strings, numbers, booleans,and null) and two structured types (objects and arrays).

No processing model defined in JSON! (neither in JSON-LD, HAL,etc.)

9 / 46

Page 10: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

extending media type semantics

what would the RESTafarian do?

probably use a vendor specific media type

$ HEAD https://data.example.com/company/Content-Type: application/vnd.example.company+json

10 / 46

Page 11: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Link header

rel=profile Link header

The 'profile' link relation type [...] allows resource representations toindicate that they are following one or more profiles. A profile isdefined not to alter the semantics of the resource representationitself, but to allow clients to learn about additional semantics [...] inaddition to those defined by the media type [...].

$ HEAD https://data.example.com/company/Content-Type: application/jsonLink: <https://data.example.com/ontology#Company>; rel="profile"

11 / 46

Page 12: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

HATEOAS?Hypermedia can be the engine of a single API.

Hypermedia cannot be the engine of cross-API interactions.

Ruben Verborgh, Hypermedia Cannot be the Engine

12 / 46

Page 13: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

focusing on dataHATEOAS is like a hypermedia state machine

data modeling is a special case for application state

media type encodes kind/type

but few missing interactions eg. CRUD

13 / 46

Page 14: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

data patterns in JSONencodings

links

types

disambiguating schemas

Let's make JSON a hypermedia format :-)

14 / 46

Page 15: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

a 1st versionan Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "id": "q6po09", "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "id": "c34dap", "name": "Apple", "ticker": "AAPL", "industry": "q6po09"}

documentation probably available at something likehttps://data.example.com/api/documentation 15 / 46

Page 16: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

things, not String-san Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "@id": "https://data.example.com/industry/q6po09", "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@id": "https://data.example.com/company/c34dap", "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

16 / 46

Page 17: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

this is its own @idan Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

17 / 46

Page 18: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

what are we dealing with?an Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "type": "Industry", "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "type": "Company", "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

18 / 46

Page 19: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

@type + URLan Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Industry" }, "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Company" }, "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

19 / 46

Page 20: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

disambiguating attributes [1/3]How to distinguish an industry's name from a company's name?

an Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Industry" }, "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Company" }, "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

20 / 46

Page 21: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

disambiguating attributes [2/3]How to distinguish an industry's name from a company's name?

an Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Industry" }, "https://data.example.com/ontology#industryName": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@type": { "@id": "https://data.example.com/ontology#Company" }, "https://data.example.com/ontology#companyName": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

21 / 46

Page 22: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

disambiguating attributes [3/3]How to distinguish an industry's name from a company's name?

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@context": { "name": { "@id": "https://data.example.com/ontology#companyName" } }, "@type": { "@id": "https://data.example.com/ontology#Company" }, "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

22 / 46

Page 23: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

contextualized data: typed valuesa Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@context": { "name": { "@id": "https://data.example.com/ontology#companyName" }, "ticker": { "@id": "https://data.example.com/ontology#ticker" }, "industry": { "@id": "https://data.example.com/ontology#industry" } }, "@type": { "@id": "https://data.example.com/ontology#Company" }, "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09" }}

23 / 46

Page 24: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

contextualized data: default vocabularya Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "@context": { "@vocab": "https://data.example.com/ontology#", "name": "companyName", "ticker": { "@type": "Ticker" }, "industry": { "@type": "@id" } }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": "https://data.example.com/industry/q6po09"}

24 / 46

Page 25: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

JSON-LDa Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { "@vocab": "https://data.example.com/ontology#", "name": "companyName", "ticker": { "@type": "Ticker" }, "industry": { "@type": "@id" } }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": "https://data.example.com/industry/q6po09"}

25 / 46

Page 26: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

not just yet another media typeis a standard

playground

in use

Google, BBC, Microsoft, Yandex, etc.

26 / 46

Page 27: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Contextualized data: external contextexternal context

$ GET https://data.example.com/general-context.jsonldContent-Type: application/ld+json

{ "@context": { "@vocab": "https://data.example.com/ontology#", "name": "companyName", "ticker": { "@type": "Ticker" }, "industry": { "@type": "@id" } }}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/jsonLink: <https://data.example.com/context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"

{ "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": "https://data.example.com/industry/q6po09"} 27 / 46

Page 28: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

linking vs embeddingan Industry entity

$ GET https://data.example.com/industry/q6po09Content-Type: application/ld+json

{ "@context": { ... }, "@type": "Industry", "name": "Fruits"}

a Company entity

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { ... }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": "https://data.example.com/industry/q6po09"}

28 / 46

Page 29: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

linking vs embeddinga Company entity with its Industry entity

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { ... }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": { "@type": "Industry", "name": "Fruits" }}

29 / 46

Page 30: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

deep linkinga Company entity with its Industry entity

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { ... }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": { "@id": "#q6po09", "@type": "Industry", "name": "Fruits" }}

Now I could use <https://data.example.com/company/c34dap#q6po09> to speakabout the Industry referenced from the document defining it.

30 / 46

Page 31: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

inlininga Company entity inlining the linked Industry entity

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { ... }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": { "@id": "https://data.example.com/industry/q6po09", "@type": "Industry", "name": "Fruits" }}

remarks

all (or part of) <https://data.example.com/industry/q6po09>'s state isinlinedthe Industry's identity+state is not under this Company's control

could even live on a different domain!applications could decide to follow links to get authoritative state 31 / 46

Page 32: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Summary so farstarted with

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "id": "c34dap", "name": "Apple", "ticker": "AAPL", "industry": "q6po09"}

32 / 46

Page 33: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Summary so farstarted with

$ GET https://data.example.com/company/c34dapContent-Type: application/json

{ "id": "c34dap", "name": "Apple", "ticker": "AAPL", "industry": "q6po09"}

ended up with something like

$ GET https://data.example.com/company/c34dapContent-Type: application/ld+json

{ "@context": { ... }, "@type": "Company", "name": "Apple", "ticker": "AAPL", "industry": "https://data.example.com/industry/q6po09"}

33 / 46

Page 34: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Immediate benefitsentities are referenced, embedded and linked together

we get for free provenance and data authority

attributes are disambiguated and can be interrogated

values are typed and can natively be links

vocabularies can be shared, reused and even checked

34 / 46

Page 35: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

introducing LDPLinked Data Platform

intersection of REST and RDF

being specced at W3C for the past 3 years

state-of-the-art of REST APIs

35 / 46

Page 36: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Container modelthe usual

$ GET https://data.example.com/company/Content-Type: application/json

{ "contains": [ "https://data.example.com/company/c34dap", ... ]}

becomes (introducing the LDP model)

$ GET https://data.example.com/company/Content-Type: application/ld+jsonLink: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"

{ "@context": { "ldp": "http://www.w3.org/ns/ldp#", "ldp:contains": { "@container": "@list", "@type": "@id" } }, "@type": [ "Companies", "ldp:BasicContainer" ], "ldp:contains": [ "https://data.example.com/company/c34dap", ... ]} 36 / 46

Page 37: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

Container model + inliningContainer's state + inlined members

$ GET https://data.example.com/company/Content-Type: application/ld+jsonLink: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"

{ "@context": { ... }, "@type": [ "Companies", "ldp:BasicContainer" ], "ldp:contains": [ { "@id": "https://data.example.com/company/c34dap", "@type": "Company", "ticker": "AAPL", "name": "Apple", "industry": { "@id": "https://data.example.com/industry/q6po09", "@type": "Industry", "name": "Fruits" } }, ... ]}

37 / 46

Page 38: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

enabling LDP interaction modelrel=type Link header

The "type" link relation can be used to indicate that the contextresource is an instance of the resource identified by the targetInternationalized Resource Identifier (IRI).

in LDP

The presence of this header asserts that the server complies with theLDP specification's constraints on HTTP interactions with LDPRs, thatis it asserts that the resource has Etags, has an RDF representation,and so on, which is not true of all Web resources served as RDF mediatypes.

$ HEAD https://data.example.com/company/Content-Type: application/ld+jsonLink: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"

38 / 46

Page 39: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

LDP interaction modelresources

Resource (LDPR) ← RDF Source (LDPRS) ← Container (LDPC) ← BasicContainer (Basic Container)

affordance

advertised through rel=type Link header, not Content-Type

a GET on a container (LDPC) returns its state (ie. its members)

resources (LDPR) are created by POSTing to the container

HTTP 201 Created + Location header

use DELETE to remove a member

use PUT to override the state of a member

use PATCH for partial updates

39 / 46

Page 40: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

LDP Paging (Working Draft) [1/2]HTTP 303 See Other

A 303 response to a GET request indicates that the origin server doesnot have a representation of the target resource [...] the Location fieldvalue refers to a resource that is descriptive of the target resource

also

server has control over the pagination mechanism

client sets preferences

semantics: snapshot, consistency, etc.

40 / 46

Page 41: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

LDP Paging (Working Draft) [2/2]use Link relations eg. rel='next'

$ GET https://data.example.com/company/303 See OtherLocation: https://data.example.com/company/?p=5YjF

$ GET https://data.example.com/company/?p=5YjF200 OKLink: <https://data.example.com/company/?p=AyOW>; rel="next"Content-Type: application/ld+json

{ ... }

Save a round-trip: HTTP 333 (being standardised)

41 / 46

Page 42: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

servicesmake it discoverable

$ HEAD https://data.example.com/company/Content-Type: application/ld+jsonLink: <https://data.example.com/company/?>; rel="http://data.example.com/api#queryService"

Use Link relation again (not yet standardised)

example

$ GET https://data.example.com/company/?offset=100&limit=50

42 / 46

Page 43: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

ad-hoc service-oriented API [1/2]$ GET https://data.example.com/api/getCompaniesByIndustry?industryName="Fruits"Content-Type: application/ld+json

{ "@context": { ... }, "results": [ { "@id": "https://data.example.com/company/c34dap", ... }, ... ]}

domain aware

more capabilities

requires to read documentation

return resource URIs and use inlining when needed

43 / 46

Page 44: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

ad-hoc service-oriented API [2/2]microservices

going further

general purpose service-oriented API?

analytics

44 / 46

Page 45: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

error handlingLDP servers MUST publish any constraints on LDP clients’ ability tocreate or update LDPRs, by adding a Link header withrel='describedby' [RFC5988] to all responses to requests which fail dueto violation of those constraints. [LDP 4.2.1.2]

so basically, HTTP 4xx + rel='describedby' Link header

use HTTP 400 for application-specific error [LDP ISSUE-98]

for machine readable errors, consider Problem Details for HTTP APIs [http-problem-06]

45 / 46

Page 46: One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014

to readHTTP/REST

Web Client Programming with Perlhttp://www.slideshare.net/RubenVerborgh/hypermedia-cannot-be-the-engine

LDP

LDP 1.0 Primer (Editor's Draft)LDP 1.0 (Editor's Draft)

RDF

http://www.w3.org/TR/2014/REC-turtle-20140225/http://semanticweb.com/introduction-to-rdf_b17953http://www.w3.org/TR/2012/REC-rdb-direct-mapping-20120927/

46 / 46