Upload
vladimir-tsukur
View
349
Download
1
Embed Size (px)
Citation preview
2016Vladimir Tsukur @ Tech Lunch
hypermedia APIs and <HATEOAS>
REST
Volodymyr Tsukur partner @
software engineering manager @
flushdia vtsukurprogram committee @
Web / HTTP API
Richardson Maturity Model
Идея! ЧЕРНЫЙ РЫНОК ВАЛЮТ!
6
DEMO TIME !
9
Method URL Task
POST /ads Create new ad
GET /ads View ads
GET /ads/{id} Get ad
PATCH / PUT /ads/{id} Update ad
DELETE /ads/{id} Delete ad
CRUD Style API
Должен же быть БИЗНЕС-ПРОЦЕСС!
if (status == Status.NEW) { publishedAt = LocalDateTime.now(); status = Status.PUBLISHED;} …
CRUD is NOT enough
12
Method URL Task
PUT /ads/{id}/publishing Publish ad
PUT /ads/{id}/expiration Expire ad
GET /ads/search/published Get published ads
API Changes
DEMO TIME !
/uri Style Adoption?
43%
Richardson Maturity Model
16
17
Task Method URL
Update ad PATCH /ads/{id}
Delete ad DELETE /ads/{id}
Publish ad PUT /ads/{id}/publishing
Expire ad PUT /ads/{id}/expiration
URL Binding & Construction
URL Change Drivers
URL Change Drivers
•monolith → micro-services •deployment requirements / proxies •renaming •optimization by locality •caching •…
20
Task Method URL
Update ad (only if NEW) PATCH /ads/{id}
Delete ad (only if NEW) DELETE /ads/{id}
Publish ad (only if NEW) PUT /ads/{id}/publishing
Expire ad (only if
PUBLISHED)PUT /ads/{id}/expiration
"Figuring" Out the Flow
Security!
22
Task Method URLUpdate ad
(only if NEW and user has permissions)
PATCH /ads/{id}
Delete ad (only if NEW and user
has permissions)DELETE /ads/{id}
Publish ad (only if NEW and user
has permissions)PUT /ads/{id}/publishing
Expire ad (only if PUBLISHED and user has permissions)
PUT /ads/{id}/expiration
Security!
Должно работать на моем iPhone 6s
!!!!!
"Hypermedia" =
{ "amount": 3000, "currency": "USD", …}
data
{ … "_links": { "publishing": { "href": "/ads/1/publishing" }, "update": { "href": "/ads/1" }, "deletion": { "href": "/ads/1" } }}
links
+
26
Link Relation Task Method
update Update ad PATCH
deletion Delete ad DELETE
publishing Publish ad PUT
expiration Expire ad PUT
Hypermedia API
DEMO TIME !
Hypermedia Client
if (ad._links.has("publishing")) { // draw publishing button / UI}
"Simple" Hypermedia
✓where to go?
✓when? - how?
Non-Hypermedia Client
Hypermedia Client
"I want hypermedia!" (2014)
0 %
7 %
14 %
21 %
28 %
Hypermedia SOAP CRUD
40%"I want hypermedia!" (2015)
Давай глубже!
«A REST API should spend almost all of its descriptive effort in defining the media type(s)
used for representing resources and driving application state, or in defining extended relation
names and/or hypertext-enabled mark-up for existing standard media types.»
Roy T. Fielding, 2008
Hypertext Application Language
Mason{ "amount": 3000, "currency": "USD", "rate": 25.8, … "@controls": { "user": { "href": "/users/1536c64" }, "ad-publish": { "href": "/ads/1536c64/publishing", "method": "PUT" } }}
Hypermedia FactorsHypermedia FactorsPokemons
level of hypermedia support
CL = Link Semantics
"_links": { "user": { "href": "/users/1" }}
IANA Link RelationsName Description RFC
self Conveys an identifier for the link's context. RFC4287
first An IRI that refers to the furthest preceding resource in a series of resources. RFC5988
last An IRI that refers to the furthest following resource in a series of resources. RFC5988
up Refers to a parent document in a hierarchy of documents. RFC5988
item The target IRI points to a resource that is a member of the collection represented by the context IRI. RFC6573
collection The target IRI points to a resource which represents the collection resource for the context IRI. RFC6573
edit Refers to a resource that can be used to edit the link's context. RFC5023
prev/previous Indicates that the link's context is a part of a series, and that the previous in the series is the link target. HTML5
next Indicates that the link's context is a part of a series, and that the next in the series is the link target. HTML5
IANA Link RelationsName Description RFC
create-form The target IRI points to a resource where a submission form can be obtained. RFC6861
edit-form The target IRI points to a resource where a submission form for editing associated resource can be obtained. RFC6861
payment Indicates a resource where payment is accepted RFC5988
latest-version Points to a resource containing the latest (e.g., current) version of the context. RFC5829
profile Identifying that a resource representation conforms to a certain profile, without affecting the non-profile semantics of the resource representation. RFC6906
search Refers to a resource that can be used to search through the link's context and related resources. OpenSearch
index Refers to an index. HTML4
about Refers to a resource that is the subject of the link's context. RFC6903
help Refers to context-sensitive help. HTML5
CL = Link Semantics
<link rel="stylesheet" src="styles.css" />
LE = Link Outbound
"_links": { "ad": { "href": "/ads/1536c64" }}
LE = Link Outbound
<a href="/ads/1536c64.html"> Buy, Rate: 25.0, USD 3000</a>
LE = Link Embedded
"_embedded": { "ad": [ { "id": "5d75544", … }, { "id": "1448cf9", … }, ]}
LE = Link Embedded
<img src="/images/cities/lviv.jpg">
LT = Templated Queries
"_links": { "ad-by-id": { "href": "/ads{/id}", "templated": true }}
LT = Templated Queries
"_links": { "ads": { "href": "/ads{?page,size,sort}", "templated": true }}
RFC 6570
LT = Templated Queries
<form method="get" action="/hotels/search"> <input name="query" type="text"> <input type="submit"></form>
LN = Non-Idemp. Updates"actions": [ { "name": "create-ad", "method": "POST", "href": "/ads", "type": "application/json", "fields": [ { "name": "type", "type": "text" }, { "name": "amount", "type": "number" }, { "name": "currency", "type": "text" }, … ] }]
<form method="post" action="/ads"> <input name="type" type="text"> <input name="amount" type="number"> <input name="currency" type="text"> <input type="submit"></form>
LN = Non-Idemp. Updates
LN = Idempotent Updates
"actions": [ { "name": "delete-ad", "method": "DELETE", "href": "/ads/1d2e9f5" }]
CM = Method Modification
"actions": [ { "name": "delete-ad", "method": "DELETE", "href": "/ads/1" }]
CM = Method Modification
"actions": [ { "name": "delete-ad", "method": "DELETE", "href": "/ads/1" }]
CR = Read Modification"_links": { "ad": [ { "name": "ad-json", "href": "/ads/1536c64", "type": "application/json" } { "name": "ad-xml", "href": "/ads/1536c64", "type": "application/xml" } ]}
Hypermedia Factors
?What about and
Hypermedia FactorsHTML XML JSON
LE ⩗ ⊗ ⊗
LO ⩗ ⊗ ⊗
LT ⩗ ⊗ ⊗
LN ⩗ ⊗ ⊗
LI ⊗ ⊗ ⊗
CR ⊗ ⊗ ⊗
CU ⩗ ⊗ ⊗
CM ⩗ ⊗ ⊗
CL ⩗ ⊗ ⊗
JSON-based Media TypesJSON-LD JSON API HAL Cj Siren Mason Uber
LE ⩗ ⩗ ⩗ ⩗ ⩗ ⩗ ⩗
LO ⩗ ⩗ ⩗ ⩗ ⩗ ⩗ ⩗
LT ⊗ ⩗ ⩗ ⩗ ⊗ ⩗ ⩗
LN ⊗ ⊗ ⊗ ⩗ ⩗ ⩗ ⩗
LI ⊗ ⊗ ⊗ ⩗ ⩗ ⩗ ⩗
CR ⊗ ⊗ ⩗ ⊗ ⩗ ⩗ ⩗
CU ⊗ ⊗ ⊗ ⊗ ⩗ ⩗ ⩗
CM ⊗ ⊗ ⊗ ⊗ ⩗ ⩗ ⩗
CL ⩗ ⩗ ⩗ ⩗ ⩗ ⩗ ⩗
Before Choosing Media Type
•list information client would want from the API
•draw state diagram -think "tasks" -"(non-)idempotent", "(un-)safe"
{ "@id": "http://black-market.com/ads/1536c64", "@context": "http://black-market.com/schema/ad.jsonld", "amount": 3000, "currency": "USD", "rate": 25.8, …}
JSON-LD
{ "@context": { "amount": "https://schema.org/amount", "currency": "https://schema.org/currency", "rate": { "@id": "http://black-market.com/schema/rate", "@type": "xsd:double" }, … }}
http://black-market.com/schema/ad.jsonld
{ "@id": "http://black-market.com/ads/1536c64", … "supportedOperations": [ { "@type": "PublishAdOperation", "method": "PUT", "expects": "#Ad" } ]}
JSON-LD + Hydra
{ "class": [ "ad" ], "properties": { "amount": 3000, "currency": "USD", … }, "links": …, "actions": [ { "name": "create-ad", "href": "/ads", "method": "POST", … } ]}
SIREN
CL = Link Semantics
"_links": { "user": { "href": "/users/1" }}
CL = Link Semantics
"_links": { "http://black-market.com/rels/user": { "href": "/users/1" }}
CL = Link Semantics
"_links": { "urn:black-market.com/rels/user": { "href": "/users/1" }}
CL = Link Semantics
"_links": { "black-market:user": { "href": "/users/1" }}
CompactURIEblack-market=http://black-market.com/rels/{rel}
black-market:user
http://black-market.com/rels/user
DEMO TIME !
Mason{ "amount": 3000, "currency": "USD", "rate": 25.8, … "@namespaces": { "black-market": { "name": "http://black-market.com/rels/" } }, "@controls": { "black-market:user": { "href": "/users/1536c64" }, "black-market:ad-publish": { "href": "/ads/1536c64/publishing", "method": "POST" } }}
А документация?
Documentation
•no URLs except of the entry point •resources •links (namespaces) •HTTP status codes, verbs •authentication, rate limiting •errors
DEMO TIME !
Profiles
✓where to go?
✓when?
✓how?
DEMO TIME !
78
Thanks! Questions?
References1. http://www.google.com.ua/trends/explore#q=web%20api%2C%20rest%20api&cmpt=q&tz= 2. http://finance.i.ua/market/ 3. http://projects.spring.io/spring-boot/ 4. http://projects.spring.io/spring-data/ 5. http://docs.spring.io/spring-data/jpa/docs/1.7.2.RELEASE/reference/html/ 6. http://projects.spring.io/spring-data-rest/ 7. http://docs.spring.io/spring-data/rest/docs/2.3.0.RELEASE/reference/html/ 8. https://spring.io/blog/2014/07/14/spring-data-rest-now-comes-with-alps-metadata 9. http://projects.spring.io/spring-hateoas/ 10. http://docs.spring.io/spring-hateoas/docs/0.17.0.RELEASE/reference/html/ 11. https://github.com/spring-projects/spring-restdocs 12. https://blog.akana.com/hypermedia-apis 13. http://www.apiacademy.co/lessons/api-design/web-api-architectural-styles 14. http://www.programmableweb.com/news/modern-api-architectural-styles-offer-developers-choices/2014/06/13 15. https://en.wikipedia.org/wiki/Hypermedia 16. http://stateless.co/hal_specification.html 17. https://github.com/kevinswiber/siren 18. https://www.mnot.net/blog/2013/06/23/linking_apis 19. http://oredev.org/2010/sessions/hypermedia-apis 20. http://vimeo.com/75106815 21. https://www.innoq.com/blog/st/2012/06/hypermedia-benefits-for-m2m-communication/ 22. http://ws-rest.org/2014/sites/default/files/wsrest2014_submission_12.pdf 23. http://www.infoq.com/news/2014/03/ca-api-survey 24. https://twitter.com/hypermediaapis 25. https://www.youtube.com/watch?v=hdSrT4yjS1g 26. https://www.youtube.com/watch?v=mZ8_QgJ5mbs 27. http://nordsc.com/ext/classification_of_http_based_apis.html 28. http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html 29. https://github.com/mamund/Building-Hypermedia-APIs 30. http://tech.blog.box.com/2013/04/get-developer-hugs-with-rich-error-handling-in-your-api/