25
Hypermedia Application Protocol @alexander_kiel Clojure Berlin 2015

Hap clojure berlin 2015

Embed Size (px)

Citation preview

Page 1: Hap clojure berlin 2015

Hypermedia Application Protocol

@alexander_kielClojure Berlin 2015

Page 2: Hap clojure berlin 2015

REST

• Constraints: Client-server, Stateless, Cacheable, Layered System, Code on demand, Uniform interface

• Uniform interface: Identification of resources, Manipulation of resources through representations, Self-descriptive messages, Hypermedia as the engine of application state (HATEOAS)

Page 3: Hap clojure berlin 2015

– Roy T. Fielding

“REST APIs must be hypertext-driven.”

Page 4: Hap clojure berlin 2015

Hypermedia Application Protocol• Hypermedia type for REST API’s

• Like HTML for API’s

• Based on Transit as transport format

• Similar to HAL1 but adds Transit, Forms and Schema

• On GitHub: Spec, Browser, ToDo app, Ring middleware, Clojure(Script) client, Transit data types for Schema

1: http://stateless.co/hal_specification.html

Page 5: Hap clojure berlin 2015

RepresentationsRepresentations are maps with the following keys.

{"~:data": {} #_"Custom Data"

“~:links”: {} #_"Links"

“~:queries”: {} #_"Queries"

“~:forms”: {} #_"Forms"

“~:embedded”: {} #_”Embedded representations"

“~:ops”: {} #_"Operations"}

Page 6: Hap clojure berlin 2015

LinksMost important hypermedia artifact

{"~:links":

{"~:self": {"~:href": "~r/"}

"~:todo/items": {"~:href": "~r/items"}}}

Page 7: Hap clojure berlin 2015

LinksMost important hypermedia artifact

{"~:links":

{"~:self": {"~:href": "~r/"}

"~:todo/items": {"~:href": "~r/items"}}}

Every representation has links under the :links key.

Page 8: Hap clojure berlin 2015

LinksMost important hypermedia artifact

{"~:links":

{"~:self": {"~:href": "~r/"}

"~:todo/items": {"~:href": "~r/items"}}}

Every link has a key. Namespace less keys are reserved.

Page 9: Hap clojure berlin 2015

LinksMost important hypermedia artifact

{"~:links":

{"~:self": {"~:href": "~r/"}

"~:todo/items": {"~:href": "~r/items"}}}

Links can have: :href and :label.

Page 10: Hap clojure berlin 2015

LinksMost important hypermedia artifact

{"~:links":

{"~:self": {"~:href": "~r/"}

"~:todo/items": {"~:href": "~r/items"}}}

:href are Transit URI’s

Page 11: Hap clojure berlin 2015

QueriesLike HTML GET Forms

{"~:queries":

{"~:filter":

{"~:href": "~rhttp://..."

"~:params": {"~:filter": {"~:type": "~SStr"}}}}}

Page 12: Hap clojure berlin 2015

QueriesLike HTML GET Forms

{"~:queries":

{"~:todo/filter":

{"~:href": "~rhttp://..."

"~:params": {"~:filter": {"~:type": "~SStr"}}}}}

Every query has a key.

Page 13: Hap clojure berlin 2015

QueriesLike HTML GET Forms

{"~:queries":

{"~:todo/filter":

{"~:href": "~rhttp://..."

"~:params": {"~:filter": {"~:type": "~SStr"}}}}}

Queries can have: :href, :params and :label.

Page 14: Hap clojure berlin 2015

QueriesLike HTML GET Forms

{"~:queries":

{"~:todo/filter":

{"~:href": "~rhttp://..."

"~:params": {"~:filter": {"~:type": "~SStr"}}}}}

Params can have: :type, :optional and :label.

Page 15: Hap clojure berlin 2015

QueriesLike HTML GET Forms

{"~:queries":

{"~:todo/filter":

{"~:href": "~rhttp://..."

"~:params": {"~:filter": {"~:type": "~SStr"}}}}}

Param types are Prismatic Schemas.

Page 16: Hap clojure berlin 2015

FormsLike HTML POST Forms - Used to create resources.

{"~:forms":

{"~:todo/create-item":

{"~:href": "~r/items"

"~:params":

{“~:label": {"~:type": "~SStr"}}}}}

Same as structure queries but different semantic.

Page 17: Hap clojure berlin 2015

Custom Payload (Data)Data can be anything, but maps are most common.

{"~:data":

{“~:label”: “Buy milk.”

“~:state”: “~:active”}}

Param types are Prismatic Schemas.

Page 18: Hap clojure berlin 2015

Custom Payload (Data)Data can be anything, but maps are most common.

{"~:data":

{“~:label”: “Buy milk.”

“~:state”: “~:active”}}

Data is keyed under :data to separate from other things.

Page 19: Hap clojure berlin 2015

Embedded RepsRepresentations can be embedded for efficiency reasons.{"~:embedded":

{"~:todo/items":

[{"~:data": {"~:label": “Buy Milk.”}

"~:links": {"~:self": {"~:href": "~rhttp://..."}}}]}}

Page 20: Hap clojure berlin 2015

Embedded RepsRepresentations can be embedded for efficiency reasons.{"~:embedded":

{"~:todo/items":

[{"~:data": {"~:label": “Buy Milk.”}

"~:links": {"~:self": {"~:href": "~rhttp://..."}}}]}}

Reps are keyed under the same key as a link would be.

Page 21: Hap clojure berlin 2015

Embedded RepsRepresentations can be embedded for efficiency reasons.{"~:embedded":

{"~:todo/items":

[{"~:data": {"~:label": “Buy Milk.”}

"~:links": {"~:self": {"~:href": "~rhttp://..."}}}]}}

Reps still have a :self link.

Page 22: Hap clojure berlin 2015

Operations

• Tell the client what is possible / allowed

• Updates: PUT of the whole representation

• Delete: simple DELETE of the resource

{"~:ops": {"~#set": [“~:update" "~:delete"]}}

Page 23: Hap clojure berlin 2015

hap-client-cli

• Clojure(Script) lib build on top of HAP semantics

• High-level operations such as: fetch, execute (query), create, update and delete

• Uses core.async

Page 24: Hap clojure berlin 2015

Create a new Resource(require '[clojure.core.async :refer [go]]) (require '[async-error.core :refer [go-try <?]]) (require '[hap-client.core :as hap])

(go-try (let [root (<? (hap/fetch "http://localhost:8080")) form (:my-form (:forms root))] (<? (hap/create form {:name "value"})))))

Page 25: Hap clojure berlin 2015

Create a new Resource(require '[clojure.core.async :refer [go]]) (require '[async-error.core :refer [go-try <?]]) (require '[hap-client.core :as hap])

(go-try (let [root (<? (hap/fetch "http://localhost:8080")) form (:my-form (:forms root))] (<? (hap/create form {:name "value"})))))

• Fetch the service document containing the form

• Create the resource using the form