one web (api?) – alexandre bertails - ippevent 10 juin 2014

Post on 14-Jun-2015

1.147 Views

Category:

Internet

4 Downloads

Preview:

Click to see full reader

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.

TRANSCRIPT

Web APIsAlexandre Bertails, Pellucid Analytics

@bertails

1 / 46

Web APIsWho are the users of my API?

What do they do with it?

How will they interact with it?

2 / 46

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

HTTP, back to the basicsresources

representations

semantics

4 / 46

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

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

IANA registry for media typesIANA registry for Media Types

Name Template Referencejson application/json [RFC7158]

7 / 46

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

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

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

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

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

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

data patterns in JSONencodings

links

types

disambiguating schemas

Let's make JSON a hypermedia format :-)

14 / 46

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

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

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

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

@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

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

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

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

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

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

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

not just yet another media typeis a standard

playground

in use

Google, BBC, Microsoft, Yandex, etc.

26 / 46

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

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

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

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

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

Summary so farstarted with

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

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

32 / 46

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

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

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

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

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

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

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

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

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

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

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

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

going further

general purpose service-oriented API?

analytics

44 / 46

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

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

top related