SlideShare a Scribd company logo
1 of 50
Download to read offline
HYPERMEDIA: 
THE MISSING ELEMENT 
to Building Adaptable Web APIs in Rails 
ハイパーメディア: RailsでWeb APIをつくるには、これが足りない 
Toru Kawamura 
@tkawa 
! 
RubyKaigi 2014
@tkawa 
Toru Kawamura 
• Freelance Ruby/Rails programmer 
• Technology Assistance Partner at 
SonicGarden Inc. 
• RESTafarian 
inspired by Yohei Yamamoto (@yohei) 
• Co-organizer of Sendagaya.rb 
• Organizer of the 
reading group of 
“RESTful Web APIs”
Web API
“Web” 
http://www.opte.org/the-internet/
http://pixabay.com/en/spider-web-net-grid-silk-drops-13516/
https://www.flickr.com/photos/tamaki/260594564/
• Private 
• For internal use 
• For SPA or dedicated 
clients only 
• Almost expected, 
almost controllable 
• Public 
• For external use 
• For general-purpose 
clients 
• Less expected, 
less controllable
“Whether an API should be RESTful or not 
depends on the requirement” 
– 「WebAPIのこれまでとこれから」by @yohei 
http://www.slideshare.net/yohei/webapi-36871915
http://pixabay.com/en/spider-web-net-grid-silk-drops-13516/
Change
Change is inevitable 
! 
Web APIs must adapt to changes 
変化は避けられない 
Web APIは変化に適応しなければならない
Two types of Change 
With versioning Without versioning 
Incompatible Compatible 
Breaks clients Does not break clients 
Breaking Change Non-Breaking Change
Breaking Changes are Harmful 
壊す変更は有害 
• Terrible user experience 
ひどいユーザ体験 
• Forces client developers to rewrite/redeploy code 
クライアント開発者にコードの書き直し・再デプロイを強いる 
• What if on …
Because of what? 
なぜ起こるの? 
With versioning Without versioning 
Incompatible Compatible 
Breaks clients Does not break clients 
Breaking Change Non-Breaking Change
Many clients are built from 
human-readable documentation 
人間が読める説明書から作られる 
クライアントがたくさんある 
GET /v1/statuses?id=#{id} GET /v1/statuses?id=#{id}
GET /v2/statuses/#{id} GET /v1/statuses?id=#{id} ×Need to rewrite code
Some clients are built from 
machine-readable documentation 
{ 
"apiVersion": "1.0.0", 
"basePath": "http:// 
petstore.swagger.wordnik.com/api", 
"resourcePath": "/store", 
"produces": [ 
"application/json" 
], 
"apis": [ 
{ 
"path": "/store/order/{orderId}", 
"operations": [ 
{ 
GET /v1/statuses?id=#{id} GET /v1/statuses?id=#{id} 
"method": "GET", 
"summary": "Find purchase order 
by ID", 
"notes": "For valid response 
try integer IDs with value <= 5. Anything 
above 5 or nonintegers will generate API 
errors", 
"type": "Order", 
"nickname": "getOrderById", 
"authorizations": {}, 
"parameters": [ 
機械が読める説明書から作られる 
クライアントもある
GET /v2/statuses/#{id} GET /v1/statuses?id=#{id} ×Need to regenerate code 
{ 
"apiVersion": "2.0.0", 
"basePath": "http:// 
petstore.swagger.wordnik.com/api", 
"resourcePath": "/store", 
"produces": [ 
"application/json" 
], 
"apis": [ 
{ 
"path": "/store/order/{orderId}", 
"operations": [ 
{ 
"method": "GET", 
"summary": "Find purchase order 
by ID", 
"notes": "For valid response 
try integer IDs with value <= 5. Anything 
above 5 or nonintegers will generate API 
errors", 
"type": "Order", 
"nickname": "getOrderById", 
"authorizations": {}, 
"parameters": [
{ 
uber: { 
Because of Coupling 
version: "1.0", 
data: [{ 
url: "http://www.ishuran.dev/notes/1", 
name: "Article", 
data: [ 
• API { 
name: changes "articleBody", 
should be reflected in clients 
value: "First note's text" 
}, 
{ 
It is name: • value: }, 
good "datePublished", 
null 
to split up explanations of the API and 
{ 
embed name: "dateCreated", 
value: "2014-them 09-11T12:into 00:31+09:00" 
each API response 
}, 
{ 
name: "dateModified", 
value: "2014-09-11T12:00:31+09:00" 
• A }, 
{ 
lot of assumptions about the API make a tight 
name: "isPartOf", 
rel: "collection", 
coupling 
url: "/notes" 
密結合のせい 
APIの変更がクライアントに反映されるべき 
APIの説明を分割して各レスポンスに埋め込むのが良い 
APIについての多大な仮定は密結合を生む
With versioning Without versioning 
Incompatible Compatible 
Breaks clients Does not break clients 
Breaking Change Non-Breaking Change 
because of the Coupling because of the Decoupling
Decoupling in a example: 
FizzBuzzaaS 
• by Stephen Mizell 
例で見る疎結合 
http://fizzbuzzaas.herokuapp.com/ 
http://smizell.com/weblog/2014/solving-fizzbuzz-with-hypermedia 
• Server knows how to calculate 
FizzBuzz for given number (<= 100) 
サーバは100までの数のFizzBuzzを計算できる 
• Server knows what the next FizzBuzz 
will be 
サーバは次のFizzBuzzが何になるか知っている 
• Client wants all FizzBuzz from one to 
the last in order 
クライアントは1から最後まで順番にすべてのFizzBuzzが欲しい 
http://sef.kloninger.com/posts/ 
201205fizzbuzz-for-managers. 
html
Coupled client 
密結合なクライアント 
answer = HTTP.get("/v1/fizzbuzz?number=#{i}") 
puts answer 
end 
"/v2/fizzbuzz/#{i}" 
(1..1000) 
(1..100).each do |i| 
• Every URL and parameter is hardcoded 
• Duplicates the server logic such as counting 
up 
すべてのURLとパラメータがハードコードされている 
カウントアップのようなサーバロジックと同じことをやっている
Decoupled client 
疎結合なクライアント 
root = HTTP.get_root 
answer = root.link('first').follow 
puts answer 
while answer.link('next').present? 
answer = answer.link('next').follow 
puts answer 
end Link ‘next’ is the key 
• No hardcoded URLs 
• Client doesn’t break when changing 
URLs / the restriction 
ハードコードされたURLなし 
URLや条件を変えてもクライアントは壊れない
The “API Call” metaphor is 
dangerous 
「APIコール」のメタファーは危険 
• We need to move away from the paradigm where 
a client arranges a URL and parameters in advance 
and calls API (like RPC…) 
URLとパラメータを用意してAPIを呼ぶというRPCのようなパラダイムから離れよう 
• What a client does next should be to choose 
from links in the response 
== HYPERMEDIA 
クライアントが次にすることはリンクから選ぶこと 
これがハイパーメディア
This is not imaginary 
but already present in HTML 
これは想像上のものではなく、すでにHTMLにある
The HTML Web 
• Web apps and websites 
have been changing 
constantly without 
breaking browsers 
• Why don’t browsers 
break on the HTML Web? 
There are links 
in HTML 
WebアプリやWebサイトはずっと変わり続けているけど 
ブラウザは壊れていないのはなぜ? 
http://www.youtypeitwepostit.com/messages
Workflow in HTML 
• Web app includes a 
(suggested) workflow 
• Workflow is represented 
by a sequence of screen 
transitions 
— Links and Forms 
Webアプリはワークフローを含む 
ワークフローは一連の画面遷移で表現される 
それはリンクとフォーム 
”RESTful Web APIs” p.11 Figure 1-7
Hypermedia show the workflow 
ハイパーメディアはワークフローを示す 
• Each screen includes what a 
browser can do next 
through links and forms like a 
“menu” 
• A browser chooses from the 
“menu” to go to the next 
step 
• This is HYPERMEDIA and 
exactly what FizzBuzzaaS 
does 
3 
4 
各画面は次に何ができるかのリンクやフォームの 
「メニュー」を含み、ブラウザはその中から選ぶ 
これがハイパーメディア
One more hint in a Crawler 
クローラーにはもう1つヒントが 
• Crawlers follow links and can submit some forms 
• Crawlers understand the data in an HTML document 
and their “meaning” 
• How can they do that? 
クローラはHTMLの中のデータと意味を理解している 
https://support.google.com/webmasters/answer/99170 どうやって?
Microdata 
<div itemscope itemtype="http://schema.org/Person"> 
My name is <span itemprop="name">Bob Smith</span> 
but people call me <span itemprop="nickname">Smithy</span>. 
Here is my home page: 
<a href="http://www.example.com" itemprop="url">www.example.com</a> 
I live in Albuquerque, NM and 
work as an <span itemprop="title">engineer</span> 
at <span itemprop="affiliation">ACME Corp</span>. 
</div> 
• Mechanism that embeds structured data within an HTML 
document 
• Document structure can change without changing data 
• Connects data with a URL that roughly represents 
the “meaning of data” (this is also a kind of link) 
Microdataは構造化データをHTMLに埋め込むしくみ 
URLに結びつけることで大まかな「データの意味」も表す
Microdata 
<div itemscope itemtype="http://schema.org/Person"> 
My name is <span itemprop="name">Bob Smith</span> 
but people call me <span schema.itemprop="org 
nickname">Smithy</span>. 
Here is my home page: 
<a href="is the http://standard www.example.vocabulary com" itemprop="promoted url">www.example.I live in Albuquerque, NM and 
by 
com</a> 
work as an Bing, <span itemprop="Google, title">at <span itemprop="affiliation">Yahoo! engineer</span> 
ACME Corp</and Yandex 
span>. 
</div> 
• Mechanism that embeds structured data within an HTML 
document 
• Document structure can change without changing data 
• Connects data with a URL that roughly represents 
the “meaning of data” (this is also a kind of link) 
http://getschema.org/index.php/Main_Page
You could build a Web API in HTML 
HTMLでWeb APIを作ることもできる 
var user = document.getItems('http://schema.org/Person')[0]; 
var name = user.properties['name'][0].itemValue; 
alert('Hello ' + name + '!'); 
• “Microdata DOM API” allows clients to extract data from HTML 
http://www.w3.org/TR/microdata/#using-the-microdata-dom-api 
Microdata DOM APIでHTMLからデータを抽出できる 
• Available in JavaScript: https://github.com/termi/Microdata-JS 
• There are also some specs for translating Microdata into JSON 
MicrodataからJSONに変換もできる 
• HTML’s great advantage is that it has links and forms built-in 
HTMLはリンクとフォームを持っているのが大きなアドバンテージ
But you probably want a 
JSON Web API… 
でもたぶんJSON Web APIが欲しいよね 
data link form 
HTML 
+Microdata ✓✓ ✓ ✓ 
JSON ✓ - - 
✓✓: including “meaning of data” 
• You have to fill in links and forms 
(also the meanings of data, if possible) 
リンクとフォームを埋めればいい(できればデータの意味も)
Links and Forms in JSON 
• Use a JSON-based 
format that can represent 
links and forms 
• There are other formats 
Siren, Collection+JSON, 
Mason, Verbose, etc 
data link form 
JSON ✓ - - 
JSON 
+Link header ✓ ✓ - 
HAL ✓ ✓ - 
JSON-LD ✓✓ ✓ - 
JSON-LD 
+Hydra ✓✓ ✓ ✓ 
UBER ✓ ✓ ✓ 
リンクとフォームを表現できる 
JSONベースのフォーマットがある 
✓✓: including “meaning of data”
A Solution
Hypermicrodata gem 
https://github.com/tkawa/hypermicrodata 
• Translate HTML into JSON on Server-side 
• Extract not only Microdata but also links and 
forms from HTML 
• Generate a JSON-based format that naturally fits 
with an explanation of meaning of data 
サーバサイドでHTMLをJSONに変換 
Microdataだけではなく 
リンクとフォームもHTMLから抽出 
データの意味も表しやすい形で 
JSONベースのフォーマットを生成
Design procedure in Rails with 
Hypermicrodata gem 
Hypermicrodata gemを使ったRailsによる設計手順 
1. Design resources 
2. Draw a state diagram 
3. Connect names of data with corresponding URLs 
4. Write HTML templates (Haml, Slim, etc) with 
Microdata markup 
1. リソース設計 
2. 状態遷移図を描く 
3. データの名前を対応するURLに結びつける 
4. HTMLテンプレートを書き 
Microdataでマークアップ 
(Then, write profiles and explanations that are not defined in 
schema.org, if necessary)
1. Design resources 
column name short description type 
text content text of note text 
published_at published time of note datetime 
(id, created_at, updated_at) (auto-generated) 
$ rails g model Note text:text published_at:datetime 
model: Note 
controller: NotesController 
routing: resources :notes
2. Draw a state diagram 
Begin with Collection & Member Resource pattern of Rails (API ver.) 
item 
collection 
Collection Member 
create*† 
update*, delete* 
* unsafe 
† non-idempotent
Collection 
of Note 
Note 
(text, published_at, 
created_at, 
updated_at, id) 
item 
collection 
create*† 
update*, delete*, 
* unsafe 
† non-idempotent 
publish* 
next, prev 
Home 
notes home
3. Connect names of data with 
corresponding URLs 
Collection of Note http://schema.org/ItemList 
Note http://schema.org/Article 
text http://schema.org/articleBody 
published_at http://schema.org/datePublished 
created_at http://schema.org/dateCreated 
updated_at http://schema.org/dateModified 
id (No need because each note has its own URL) 
Home http://schema.org/SiteNavigationElement
4. Write HTML templates with Microdata 
Collection of Note 
%div{itemscope: true, itemtype: 'http://schema.org/ItemList', 
itemid: notes_url, data: {main_item: true}} 
- @notes.each do |note| 
= link_to note.text.truncate(20), note, 
rel: 'item', itemprop: 'hasPart' 
/app/views/notes/index.html.haml 
GET /notes HTTP/1.1 
Host: www.example.com 
Accept: application/vnd.amundsen-uber+json 
= form_for Note.new do |f| 
= f.text_field :text 
= f.submit rel: 'create' 
{ 
"uber": { 
"version": "1.0", 
"data": [{ 
"url": "http://www.example.com/notes", 
"name": "ItemList", 
"data": [ 
{ "name": "hasPart", "rel": "item", "url": "/notes/1" }, 
{ "name": "hasPart", "rel": "item", "url": "/notes/2" }, 
{ "rel": "create", "url": "/notes", "action": "append", 
"model": "note%5Btext%5D={text}" }, 
{ "rel": "profile", "url": "/assets/note.alps"} 
] 
}] 
} 
} 
Link 
Form
%div{itemscope: true, itemtype: 'http://schema.org/Article', 
itemid: note_url(@note), data: {main_item: true}} 
/app/views/notes/show.html.haml 
%span{itemprop: 'articleBody'}= @note.text 
%span{itemprop: 'datePublished'}= @note.published_at 
%span{itemprop: 'dateCreated'}= @note.created_at 
%span{itemprop: 'dateModified'}= @note.updated_at 
= form_for @note, method: :put do |f| 
= f.text_field :text 
= f.submit rel: 'update' 
= button_to 'Destroy', @note, method: :delete, rel: 'delete' 
= button_to 'Publish', publish_note_path(@note), rel: 'publish' unless @note.published? 
= link_to 'Next note', note_path(@note.next), rel: 'next' if @note.next 
= link_to 'Prev note', note_path(@note.prev), rel: 'prev' if @note.prev 
= link_to 'Collection of Note', notes_path, rel: 'collection', itemprop: 'isPartOf' 
GET /notes/1 HTTP/1.1 
Host: www.example.com 
Accept: application/vnd.amundsen-uber+json 
Note 
{ 
"uber": { 
"version": "1.0", 
"data": [{ 
"url": "http://www.example.com/notes/1", 
"name": "Article", 
"data": [ 
{ "name": "articleBody", "value": "First note's text" }, 
{ "name": "datePublished", "value": null }, 
{ "name": "dateCreated", "value": "2014-09-11T12:00:31+09:00" }, 
{ "name": "dateModified", "value": "2014-09-11T12:00:31+09:00" }, 
{ "name": "isPartOf", "rel": "collection", "url": "/notes" }, 
{ "rel": "update", "url": "/notes/1", "action": "replace", 
"model": "note%5Btext%5D={text}" }, 
{ "rel": "delete", "url": "/notes/1", "action": "remove" }, 
{ "rel": "publish", "url": "/notes/1/publish", "action": "append" }, 
{ "rel": "next", "url": "/notes/2" }, 
{ "rel": "profile", "url": "/assets/note.alps" } 
] 
}] 
} 
}
%div{itemscope: true, itemtype: 'http://schema.org/Article', 
itemid: note_url(@note), data: {main_item: true}} 
%span{itemprop: 'articleBody'}= @note.text 
%span{itemprop: 'datePublished'}= @note.published_at 
%span{itemprop: 'dateCreated'}= @note.created_at 
%span{itemprop: 'dateModified'}= @note.updated_at 
= form_for @note, method: :put do |f| 
= f.text_field :text 
= f.submit rel: 'update' 
= button_to 'Destroy', @note, method: :delete, rel: 'delete' 
= button_to 'Publish', publish_note_path(@note), rel: 'publish' unless @note.published? 
= link_to 'Next note', note_path(@note.next), rel: 'next' if @note.next 
= link_to 'Prev note', note_path(@note.prev), rel: 'prev' if @note.prev 
= link_to 'Collection of Note', notes_path, rel: 'collection', itemprop: 'isPartOf' 
Note 
= button_to 'Publish', publish_note_path(@note), 
= link_to 'Next note', note_path(@note.next), 
= link_to 'Prev note', note_path(@note.prev), 
{ 
"uber": { 
rel: 'publish' unless @note.published? 
rel: 'next' if @note.next 
rel: 'prev' if @note.prev 
"version": "1.0", 
"data": [{ 
"url": "http://www.example.com/notes/1", 
"name": "Article", 
"data": [ 
explanation of 
restriction 
Now you can publish, 
but cannot go prev 
{ "name": "articleBody", "value": "First note's text" }, 
{ "name": "datePublished", "value": null }, 
{ "name": "dateCreated", "value": "2014-09-11T12:00:31+09:00" }, 
{ "{ rel": "name": "publish", "dateModified", "url": "value": "/"2014-notes/09-11T12:1/publish", 
00:31+09:00" }, 
"{ action": "name": "isPartOf", "append" "rel": }, 
"collection", "url": "/notes" }, 
{ "rel": "update", "url": "/notes/1", "action": "replace", 
{ "rel": "model": "next", "note%5Btext%"url": 5D={text}" "/notes/}, 
2" }, 
{ "rel": "delete", "url": "/notes/1", "action": "remove" }, 
{ "rel": "publish", "url": "/notes/1/publish", "action": "append" }, 
{ "rel": "next", "url": "/notes/2" }, 
{ "rel": "profile", "url": "/assets/note.alps" } 
] 
}] 
} 
}
3 Pros of this design procedure 
• DRY 
• When providing both HTML and JSON 
• Awareness of links and forms 
• Framing the API as an HTML Web app gets you 
focused on these state transition 
• Constraints 
• “Constraints are liberating” 
この設計手順の3つのメリット 
HTMLとJSON両方提供するならDRY 
APIをWebアプリと同じように考えることで状態遷移に着目し 
リンクとフォームを意識できる 
「制約は自由をもたらす」
If you want to write only JSON, 
you should keep in mind 
もしJSONだけを書くときは注意すること 
• To stay focused on the link/form pattern: 
• Draw a state diagram 
リンク・フォームを意識するために 
状態遷移図を描きましょう 
• To keep your API decoupled: 
• Use view templates or representers such as Jbuilder/RABL 
instead of model.to_json 
疎結合のために、model.to_jsonはやめて 
ビューテンプレートを使いましょう 
• Use a JSON-based format with links and forms 
リンクとフォームを持ったJSONベースのフォーマットを使いましょう 
• In addition, it is better to use standard names such as schema.org 
schema.orgのような標準名を使うとさらに良いです
“WebアプリとWeb APIを分けて考えない” 
“Don’t consider Web app and Web API separately” 
– 「Webを支える技術」@yohei
Conclusion: 
Design Your Web API the same way 
as an HTML Web App 
結論: Web APIはHTML Webアプリと同じように設計しよう 
• A Web API is nothing special, It just has a different 
representation format 
Web APIは特別なものではなく、ただ表現フォーマットが違うだけ 
• Awareness of state transitions by drawing a 
diagram will remind you of links and forms 
状態遷移図を描いて状態遷移を意識することで、リンクやフォームを忘れずにすむ
Finally 
• Unfortunately, no de-facto standard JSON format, 
client implementations, libraries, etc 
残念ながら、デファクトスタンダードがない 
• We can do better by focusing on the principles and 
constraints of REST 
RESTの制約・原則を意識するともっとうまくできる 
• Hypermedia is one of the most important elements of 
REST, and a key step toward building Web APIs 
adaptable to change 
ハイパーメディアはRESTの最も重要な要素で 
変化に適応できるWeb APIへの重要なステップ
Build a Better & Adaptable Web API. 
Thank you for your attention. 
References 
• L. Richardson & M. Amundsen “RESTful Web APIs” (O’Reilly) 
• 山本陽平 “Webを支える技術” (技術評論社) 
• Designing for Reuse: Creating APIs for the Future 
http://www.oscon.com/oscon2014/public/schedule/detail/34922 
• API Design Workshop 配布資料 
http://events.layer7tech.com/tokyo-wrk 
• https://speakerdeck.com/zdne/robust-mobile-clients-v2 
• http://www.slideshare.net/yohei/webapi-36871915 
• http://smizell.com/weblog/2014/solving-fizzbuzz-with-hypermedia 
• 山口 徹 “Web API デザインの鉄則” WEB+DB PRESS Vol.82

More Related Content

What's hot

Webservices Overview : XML RPC, SOAP and REST
Webservices Overview : XML RPC, SOAP and RESTWebservices Overview : XML RPC, SOAP and REST
Webservices Overview : XML RPC, SOAP and RESTPradeep Kumar
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding RESTNitin Pande
 
Resource-Oriented Architecture (ROA) and REST
Resource-Oriented Architecture (ROA) and RESTResource-Oriented Architecture (ROA) and REST
Resource-Oriented Architecture (ROA) and RESTIASA
 
Restful Web Services
Restful Web ServicesRestful Web Services
Restful Web ServicesAngelin R
 
How to build a rest api.pptx
How to build a rest api.pptxHow to build a rest api.pptx
How to build a rest api.pptxHarry Potter
 
External Data Access with jQuery
External Data Access with jQueryExternal Data Access with jQuery
External Data Access with jQueryDoncho Minkov
 
Rest and the hypermedia constraint
Rest and the hypermedia constraintRest and the hypermedia constraint
Rest and the hypermedia constraintInviqa
 
Austin Day of Rest - Introduction
Austin Day of Rest - IntroductionAustin Day of Rest - Introduction
Austin Day of Rest - IntroductionHandsOnWP.com
 
API Design & Security in django
API Design & Security in djangoAPI Design & Security in django
API Design & Security in djangoTareque Hossain
 
Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco Software
 
How to build a rest api
How to build a rest apiHow to build a rest api
How to build a rest apiHoang Nguyen
 
Resource Oriented Architectures
Resource Oriented ArchitecturesResource Oriented Architectures
Resource Oriented ArchitecturesGabriele Lana
 
JSON API: Não reinvente a roda
JSON API: Não reinvente a rodaJSON API: Não reinvente a roda
JSON API: Não reinvente a rodaPedro Cavalheiro
 
Pragmatic REST: recent trends in API design
Pragmatic REST: recent trends in API designPragmatic REST: recent trends in API design
Pragmatic REST: recent trends in API designMarsh Gardiner
 
Stay Out Please
Stay Out PleaseStay Out Please
Stay Out Pleaseefim13
 
RESTful Web Services
RESTful Web ServicesRESTful Web Services
RESTful Web ServicesGreg Hines
 
REST & RESTful Web Service
REST & RESTful Web ServiceREST & RESTful Web Service
REST & RESTful Web ServiceHoan Vu Tran
 
RESTful API-centric Universe
RESTful API-centric UniverseRESTful API-centric Universe
RESTful API-centric UniverseTihomir Opačić
 

What's hot (20)

Webservices Overview : XML RPC, SOAP and REST
Webservices Overview : XML RPC, SOAP and RESTWebservices Overview : XML RPC, SOAP and REST
Webservices Overview : XML RPC, SOAP and REST
 
Rest web services
Rest web servicesRest web services
Rest web services
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
 
Resource-Oriented Architecture (ROA) and REST
Resource-Oriented Architecture (ROA) and RESTResource-Oriented Architecture (ROA) and REST
Resource-Oriented Architecture (ROA) and REST
 
Restful Web Services
Restful Web ServicesRestful Web Services
Restful Web Services
 
How to build a rest api.pptx
How to build a rest api.pptxHow to build a rest api.pptx
How to build a rest api.pptx
 
External Data Access with jQuery
External Data Access with jQueryExternal Data Access with jQuery
External Data Access with jQuery
 
Rest and the hypermedia constraint
Rest and the hypermedia constraintRest and the hypermedia constraint
Rest and the hypermedia constraint
 
Austin Day of Rest - Introduction
Austin Day of Rest - IntroductionAustin Day of Rest - Introduction
Austin Day of Rest - Introduction
 
API Design & Security in django
API Design & Security in djangoAPI Design & Security in django
API Design & Security in django
 
Rest API
Rest APIRest API
Rest API
 
Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64
 
How to build a rest api
How to build a rest apiHow to build a rest api
How to build a rest api
 
Resource Oriented Architectures
Resource Oriented ArchitecturesResource Oriented Architectures
Resource Oriented Architectures
 
JSON API: Não reinvente a roda
JSON API: Não reinvente a rodaJSON API: Não reinvente a roda
JSON API: Não reinvente a roda
 
Pragmatic REST: recent trends in API design
Pragmatic REST: recent trends in API designPragmatic REST: recent trends in API design
Pragmatic REST: recent trends in API design
 
Stay Out Please
Stay Out PleaseStay Out Please
Stay Out Please
 
RESTful Web Services
RESTful Web ServicesRESTful Web Services
RESTful Web Services
 
REST & RESTful Web Service
REST & RESTful Web ServiceREST & RESTful Web Service
REST & RESTful Web Service
 
RESTful API-centric Universe
RESTful API-centric UniverseRESTful API-centric Universe
RESTful API-centric Universe
 

Viewers also liked

SmartNews Ads System - AWS Summit Tokyo 2015
SmartNews Ads System - AWS Summit Tokyo 2015SmartNews Ads System - AWS Summit Tokyo 2015
SmartNews Ads System - AWS Summit Tokyo 2015SmartNews, Inc.
 
RESTful Meetup vol.3 Introduction
RESTful Meetup vol.3 IntroductionRESTful Meetup vol.3 Introduction
RESTful Meetup vol.3 IntroductionToru Kawamura
 
How to bake delicious cookie (RESTful Meetup #03)
How to bake delicious cookie (RESTful Meetup #03)How to bake delicious cookie (RESTful Meetup #03)
How to bake delicious cookie (RESTful Meetup #03)Toru Yamaguchi
 
Rails Gems realize RESTful modeling patterns
Rails Gems realize RESTful modeling patternsRails Gems realize RESTful modeling patterns
Rails Gems realize RESTful modeling patternsToru Kawamura
 
RESTful #とは RailsスタイルからRESTを学ぼう
RESTful #とは RailsスタイルからRESTを学ぼうRESTful #とは RailsスタイルからRESTを学ぼう
RESTful #とは RailsスタイルからRESTを学ぼうToru Kawamura
 
WebAPIのこれまでとこれから
WebAPIのこれまでとこれからWebAPIのこれまでとこれから
WebAPIのこれまでとこれからYohei Yamamoto
 
チラシルiOSでの広告枠開発
チラシルiOSでの広告枠開発チラシルiOSでの広告枠開発
チラシルiOSでの広告枠開発Satoshi Takano
 
B2B2Cなヘルスケアサービスの作り方
B2B2Cなヘルスケアサービスの作り方B2B2Cなヘルスケアサービスの作り方
B2B2Cなヘルスケアサービスの作り方Tomohiro MITSUMUNE
 
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜Kentaro Matsumae
 
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先Kazuho Oku
 
Web Clients for Ruby and What they should be in the future
Web Clients for Ruby and What they should be in the futureWeb Clients for Ruby and What they should be in the future
Web Clients for Ruby and What they should be in the futureToru Kawamura
 
DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -Tomoya Kabe
 
Why HTML Form dose not support PUT & DELETE ?
Why HTML Form dose not support PUT & DELETE ?Why HTML Form dose not support PUT & DELETE ?
Why HTML Form dose not support PUT & DELETE ?Jxck Jxck
 
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Toru Kawamura
 
リコーUCSの開発をリーンスタートアップ的視点でふりかえる
リコーUCSの開発をリーンスタートアップ的視点でふりかえるリコーUCSの開発をリーンスタートアップ的視点でふりかえる
リコーUCSの開発をリーンスタートアップ的視点でふりかえるYohei Yamamoto
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話Takuto Wada
 

Viewers also liked (20)

SmartNews Ads System - AWS Summit Tokyo 2015
SmartNews Ads System - AWS Summit Tokyo 2015SmartNews Ads System - AWS Summit Tokyo 2015
SmartNews Ads System - AWS Summit Tokyo 2015
 
RESTful Meetup vol.3 Introduction
RESTful Meetup vol.3 IntroductionRESTful Meetup vol.3 Introduction
RESTful Meetup vol.3 Introduction
 
How to bake delicious cookie (RESTful Meetup #03)
How to bake delicious cookie (RESTful Meetup #03)How to bake delicious cookie (RESTful Meetup #03)
How to bake delicious cookie (RESTful Meetup #03)
 
Rails Gems realize RESTful modeling patterns
Rails Gems realize RESTful modeling patternsRails Gems realize RESTful modeling patterns
Rails Gems realize RESTful modeling patterns
 
RESTful #とは RailsスタイルからRESTを学ぼう
RESTful #とは RailsスタイルからRESTを学ぼうRESTful #とは RailsスタイルからRESTを学ぼう
RESTful #とは RailsスタイルからRESTを学ぼう
 
WebAPIのこれまでとこれから
WebAPIのこれまでとこれからWebAPIのこれまでとこれから
WebAPIのこれまでとこれから
 
チラシルiOSでの広告枠開発
チラシルiOSでの広告枠開発チラシルiOSでの広告枠開発
チラシルiOSでの広告枠開発
 
B2B2Cなヘルスケアサービスの作り方
B2B2Cなヘルスケアサービスの作り方B2B2Cなヘルスケアサービスの作り方
B2B2Cなヘルスケアサービスの作り方
 
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
 
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
 
Web Clients for Ruby and What they should be in the future
Web Clients for Ruby and What they should be in the futureWeb Clients for Ruby and What they should be in the future
Web Clients for Ruby and What they should be in the future
 
Reusable APIs
Reusable APIsReusable APIs
Reusable APIs
 
DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -
 
Why HTML Form dose not support PUT & DELETE ?
Why HTML Form dose not support PUT & DELETE ?Why HTML Form dose not support PUT & DELETE ?
Why HTML Form dose not support PUT & DELETE ?
 
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
 
Web API入門
Web API入門Web API入門
Web API入門
 
Rest ful api設計入門
Rest ful api設計入門Rest ful api設計入門
Rest ful api設計入門
 
リコーUCSの開発をリーンスタートアップ的視点でふりかえる
リコーUCSの開発をリーンスタートアップ的視点でふりかえるリコーUCSの開発をリーンスタートアップ的視点でふりかえる
リコーUCSの開発をリーンスタートアップ的視点でふりかえる
 
RESTfulとは
RESTfulとはRESTfulとは
RESTfulとは
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話
 

Similar to Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails

Lies you have been told about REST
Lies you have been told about RESTLies you have been told about REST
Lies you have been told about RESTdarrelmiller71
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsTom Johnson
 
What is API - Understanding API Simplified
What is API - Understanding API SimplifiedWhat is API - Understanding API Simplified
What is API - Understanding API SimplifiedJubin Aghara
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDBMongoDB
 
Web Services PHP Tutorial
Web Services PHP TutorialWeb Services PHP Tutorial
Web Services PHP TutorialLorna Mitchell
 
Can you keep a secret? (XP Days 2017)
Can you keep a secret? (XP Days 2017)Can you keep a secret? (XP Days 2017)
Can you keep a secret? (XP Days 2017)Valerii Moisieienko
 
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...Tom Johnson
 
Building RESTful APIs
Building RESTful APIsBuilding RESTful APIs
Building RESTful APIsSilota Inc.
 
Building with linked_in_api
Building with linked_in_apiBuilding with linked_in_api
Building with linked_in_apiMatchFWD
 
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotionAPIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotionjavier ramirez
 
Azure DocumentDB for Healthcare Integration - Part 2
Azure DocumentDB for Healthcare Integration - Part 2Azure DocumentDB for Healthcare Integration - Part 2
Azure DocumentDB for Healthcare Integration - Part 2BizTalk360
 
Build your APIs with apigility
Build your APIs with apigilityBuild your APIs with apigility
Build your APIs with apigilityChristian Varela
 
RESTful web services with Groovy on Grails by Vugar Suleymanov
RESTful web services with Groovy on Grails by Vugar SuleymanovRESTful web services with Groovy on Grails by Vugar Suleymanov
RESTful web services with Groovy on Grails by Vugar SuleymanovVuqar Suleymanov
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformAntonio Peric-Mazar
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformAntonio Peric-Mazar
 
(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery GuideMark Rackley
 
Создание API, которое полюбят разработчики. Глубокое погружение
Создание API, которое полюбят разработчики. Глубокое погружениеСоздание API, которое полюбят разработчики. Глубокое погружение
Создание API, которое полюбят разработчики. Глубокое погружениеSQALab
 
Go Fullstack: JSF for Public Sites (CONFESS 2012)
Go Fullstack: JSF for Public Sites (CONFESS 2012)Go Fullstack: JSF for Public Sites (CONFESS 2012)
Go Fullstack: JSF for Public Sites (CONFESS 2012)Michael Kurz
 

Similar to Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (20)

Lies you have been told about REST
Lies you have been told about RESTLies you have been told about REST
Lies you have been told about REST
 
API Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIsAPI Workshop: Deep dive into REST APIs
API Workshop: Deep dive into REST APIs
 
What is API - Understanding API Simplified
What is API - Understanding API SimplifiedWhat is API - Understanding API Simplified
What is API - Understanding API Simplified
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDB
 
Web Services PHP Tutorial
Web Services PHP TutorialWeb Services PHP Tutorial
Web Services PHP Tutorial
 
Can you keep a secret? (XP Days 2017)
Can you keep a secret? (XP Days 2017)Can you keep a secret? (XP Days 2017)
Can you keep a secret? (XP Days 2017)
 
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
 
Building RESTful APIs
Building RESTful APIsBuilding RESTful APIs
Building RESTful APIs
 
Building with linked_in_api
Building with linked_in_apiBuilding with linked_in_api
Building with linked_in_api
 
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotionAPIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
APIs REST Usables con Hypermedia por Javier Ramirez, para codemotion
 
Azure DocumentDB for Healthcare Integration - Part 2
Azure DocumentDB for Healthcare Integration - Part 2Azure DocumentDB for Healthcare Integration - Part 2
Azure DocumentDB for Healthcare Integration - Part 2
 
Build your APIs with apigility
Build your APIs with apigilityBuild your APIs with apigility
Build your APIs with apigility
 
RESTful web services with Groovy on Grails by Vugar Suleymanov
RESTful web services with Groovy on Grails by Vugar SuleymanovRESTful web services with Groovy on Grails by Vugar Suleymanov
RESTful web services with Groovy on Grails by Vugar Suleymanov
 
Design Web Api
Design Web ApiDesign Web Api
Design Web Api
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
Restful webservices
Restful webservicesRestful webservices
Restful webservices
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide(Updated) SharePoint & jQuery Guide
(Updated) SharePoint & jQuery Guide
 
Создание API, которое полюбят разработчики. Глубокое погружение
Создание API, которое полюбят разработчики. Глубокое погружениеСоздание API, которое полюбят разработчики. Глубокое погружение
Создание API, которое полюбят разработчики. Глубокое погружение
 
Go Fullstack: JSF for Public Sites (CONFESS 2012)
Go Fullstack: JSF for Public Sites (CONFESS 2012)Go Fullstack: JSF for Public Sites (CONFESS 2012)
Go Fullstack: JSF for Public Sites (CONFESS 2012)
 

More from Toru Kawamura

RailsスタイルからRESTを学ぼう よちがや.rb
RailsスタイルからRESTを学ぼう よちがや.rbRailsスタイルからRESTを学ぼう よちがや.rb
RailsスタイルからRESTを学ぼう よちがや.rbToru Kawamura
 
リソースモデリングパターンの提案 #sendagayarb
リソースモデリングパターンの提案 #sendagayarbリソースモデリングパターンの提案 #sendagayarb
リソースモデリングパターンの提案 #sendagayarbToru Kawamura
 
返信と@ツイートの仕様変更と提案 #twtr_hack
返信と@ツイートの仕様変更と提案 #twtr_hack返信と@ツイートの仕様変更と提案 #twtr_hack
返信と@ツイートの仕様変更と提案 #twtr_hackToru Kawamura
 
RESTとRailsスタイル
RESTとRailsスタイルRESTとRailsスタイル
RESTとRailsスタイルToru Kawamura
 
OAuth Echo の Rails Gem
OAuth Echo の Rails GemOAuth Echo の Rails Gem
OAuth Echo の Rails GemToru Kawamura
 

More from Toru Kawamura (6)

真のREST
真のREST真のREST
真のREST
 
RailsスタイルからRESTを学ぼう よちがや.rb
RailsスタイルからRESTを学ぼう よちがや.rbRailsスタイルからRESTを学ぼう よちがや.rb
RailsスタイルからRESTを学ぼう よちがや.rb
 
リソースモデリングパターンの提案 #sendagayarb
リソースモデリングパターンの提案 #sendagayarbリソースモデリングパターンの提案 #sendagayarb
リソースモデリングパターンの提案 #sendagayarb
 
返信と@ツイートの仕様変更と提案 #twtr_hack
返信と@ツイートの仕様変更と提案 #twtr_hack返信と@ツイートの仕様変更と提案 #twtr_hack
返信と@ツイートの仕様変更と提案 #twtr_hack
 
RESTとRailsスタイル
RESTとRailsスタイルRESTとRailsスタイル
RESTとRailsスタイル
 
OAuth Echo の Rails Gem
OAuth Echo の Rails GemOAuth Echo の Rails Gem
OAuth Echo の Rails Gem
 

Recently uploaded

TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 

Recently uploaded (20)

TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 

Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails

  • 1. HYPERMEDIA: THE MISSING ELEMENT to Building Adaptable Web APIs in Rails ハイパーメディア: RailsでWeb APIをつくるには、これが足りない Toru Kawamura @tkawa ! RubyKaigi 2014
  • 2. @tkawa Toru Kawamura • Freelance Ruby/Rails programmer • Technology Assistance Partner at SonicGarden Inc. • RESTafarian inspired by Yohei Yamamoto (@yohei) • Co-organizer of Sendagaya.rb • Organizer of the reading group of “RESTful Web APIs”
  • 7. • Private • For internal use • For SPA or dedicated clients only • Almost expected, almost controllable • Public • For external use • For general-purpose clients • Less expected, less controllable
  • 8. “Whether an API should be RESTful or not depends on the requirement” – 「WebAPIのこれまでとこれから」by @yohei http://www.slideshare.net/yohei/webapi-36871915
  • 11. Change is inevitable ! Web APIs must adapt to changes 変化は避けられない Web APIは変化に適応しなければならない
  • 12. Two types of Change With versioning Without versioning Incompatible Compatible Breaks clients Does not break clients Breaking Change Non-Breaking Change
  • 13. Breaking Changes are Harmful 壊す変更は有害 • Terrible user experience ひどいユーザ体験 • Forces client developers to rewrite/redeploy code クライアント開発者にコードの書き直し・再デプロイを強いる • What if on …
  • 14. Because of what? なぜ起こるの? With versioning Without versioning Incompatible Compatible Breaks clients Does not break clients Breaking Change Non-Breaking Change
  • 15. Many clients are built from human-readable documentation 人間が読める説明書から作られる クライアントがたくさんある GET /v1/statuses?id=#{id} GET /v1/statuses?id=#{id}
  • 16. GET /v2/statuses/#{id} GET /v1/statuses?id=#{id} ×Need to rewrite code
  • 17. Some clients are built from machine-readable documentation { "apiVersion": "1.0.0", "basePath": "http:// petstore.swagger.wordnik.com/api", "resourcePath": "/store", "produces": [ "application/json" ], "apis": [ { "path": "/store/order/{orderId}", "operations": [ { GET /v1/statuses?id=#{id} GET /v1/statuses?id=#{id} "method": "GET", "summary": "Find purchase order by ID", "notes": "For valid response try integer IDs with value <= 5. Anything above 5 or nonintegers will generate API errors", "type": "Order", "nickname": "getOrderById", "authorizations": {}, "parameters": [ 機械が読める説明書から作られる クライアントもある
  • 18. GET /v2/statuses/#{id} GET /v1/statuses?id=#{id} ×Need to regenerate code { "apiVersion": "2.0.0", "basePath": "http:// petstore.swagger.wordnik.com/api", "resourcePath": "/store", "produces": [ "application/json" ], "apis": [ { "path": "/store/order/{orderId}", "operations": [ { "method": "GET", "summary": "Find purchase order by ID", "notes": "For valid response try integer IDs with value <= 5. Anything above 5 or nonintegers will generate API errors", "type": "Order", "nickname": "getOrderById", "authorizations": {}, "parameters": [
  • 19. { uber: { Because of Coupling version: "1.0", data: [{ url: "http://www.ishuran.dev/notes/1", name: "Article", data: [ • API { name: changes "articleBody", should be reflected in clients value: "First note's text" }, { It is name: • value: }, good "datePublished", null to split up explanations of the API and { embed name: "dateCreated", value: "2014-them 09-11T12:into 00:31+09:00" each API response }, { name: "dateModified", value: "2014-09-11T12:00:31+09:00" • A }, { lot of assumptions about the API make a tight name: "isPartOf", rel: "collection", coupling url: "/notes" 密結合のせい APIの変更がクライアントに反映されるべき APIの説明を分割して各レスポンスに埋め込むのが良い APIについての多大な仮定は密結合を生む
  • 20. With versioning Without versioning Incompatible Compatible Breaks clients Does not break clients Breaking Change Non-Breaking Change because of the Coupling because of the Decoupling
  • 21. Decoupling in a example: FizzBuzzaaS • by Stephen Mizell 例で見る疎結合 http://fizzbuzzaas.herokuapp.com/ http://smizell.com/weblog/2014/solving-fizzbuzz-with-hypermedia • Server knows how to calculate FizzBuzz for given number (<= 100) サーバは100までの数のFizzBuzzを計算できる • Server knows what the next FizzBuzz will be サーバは次のFizzBuzzが何になるか知っている • Client wants all FizzBuzz from one to the last in order クライアントは1から最後まで順番にすべてのFizzBuzzが欲しい http://sef.kloninger.com/posts/ 201205fizzbuzz-for-managers. html
  • 22. Coupled client 密結合なクライアント answer = HTTP.get("/v1/fizzbuzz?number=#{i}") puts answer end "/v2/fizzbuzz/#{i}" (1..1000) (1..100).each do |i| • Every URL and parameter is hardcoded • Duplicates the server logic such as counting up すべてのURLとパラメータがハードコードされている カウントアップのようなサーバロジックと同じことをやっている
  • 23. Decoupled client 疎結合なクライアント root = HTTP.get_root answer = root.link('first').follow puts answer while answer.link('next').present? answer = answer.link('next').follow puts answer end Link ‘next’ is the key • No hardcoded URLs • Client doesn’t break when changing URLs / the restriction ハードコードされたURLなし URLや条件を変えてもクライアントは壊れない
  • 24. The “API Call” metaphor is dangerous 「APIコール」のメタファーは危険 • We need to move away from the paradigm where a client arranges a URL and parameters in advance and calls API (like RPC…) URLとパラメータを用意してAPIを呼ぶというRPCのようなパラダイムから離れよう • What a client does next should be to choose from links in the response == HYPERMEDIA クライアントが次にすることはリンクから選ぶこと これがハイパーメディア
  • 25. This is not imaginary but already present in HTML これは想像上のものではなく、すでにHTMLにある
  • 26. The HTML Web • Web apps and websites have been changing constantly without breaking browsers • Why don’t browsers break on the HTML Web? There are links in HTML WebアプリやWebサイトはずっと変わり続けているけど ブラウザは壊れていないのはなぜ? http://www.youtypeitwepostit.com/messages
  • 27. Workflow in HTML • Web app includes a (suggested) workflow • Workflow is represented by a sequence of screen transitions — Links and Forms Webアプリはワークフローを含む ワークフローは一連の画面遷移で表現される それはリンクとフォーム ”RESTful Web APIs” p.11 Figure 1-7
  • 28. Hypermedia show the workflow ハイパーメディアはワークフローを示す • Each screen includes what a browser can do next through links and forms like a “menu” • A browser chooses from the “menu” to go to the next step • This is HYPERMEDIA and exactly what FizzBuzzaaS does 3 4 各画面は次に何ができるかのリンクやフォームの 「メニュー」を含み、ブラウザはその中から選ぶ これがハイパーメディア
  • 29. One more hint in a Crawler クローラーにはもう1つヒントが • Crawlers follow links and can submit some forms • Crawlers understand the data in an HTML document and their “meaning” • How can they do that? クローラはHTMLの中のデータと意味を理解している https://support.google.com/webmasters/answer/99170 どうやって?
  • 30. Microdata <div itemscope itemtype="http://schema.org/Person"> My name is <span itemprop="name">Bob Smith</span> but people call me <span itemprop="nickname">Smithy</span>. Here is my home page: <a href="http://www.example.com" itemprop="url">www.example.com</a> I live in Albuquerque, NM and work as an <span itemprop="title">engineer</span> at <span itemprop="affiliation">ACME Corp</span>. </div> • Mechanism that embeds structured data within an HTML document • Document structure can change without changing data • Connects data with a URL that roughly represents the “meaning of data” (this is also a kind of link) Microdataは構造化データをHTMLに埋め込むしくみ URLに結びつけることで大まかな「データの意味」も表す
  • 31. Microdata <div itemscope itemtype="http://schema.org/Person"> My name is <span itemprop="name">Bob Smith</span> but people call me <span schema.itemprop="org nickname">Smithy</span>. Here is my home page: <a href="is the http://standard www.example.vocabulary com" itemprop="promoted url">www.example.I live in Albuquerque, NM and by com</a> work as an Bing, <span itemprop="Google, title">at <span itemprop="affiliation">Yahoo! engineer</span> ACME Corp</and Yandex span>. </div> • Mechanism that embeds structured data within an HTML document • Document structure can change without changing data • Connects data with a URL that roughly represents the “meaning of data” (this is also a kind of link) http://getschema.org/index.php/Main_Page
  • 32. You could build a Web API in HTML HTMLでWeb APIを作ることもできる var user = document.getItems('http://schema.org/Person')[0]; var name = user.properties['name'][0].itemValue; alert('Hello ' + name + '!'); • “Microdata DOM API” allows clients to extract data from HTML http://www.w3.org/TR/microdata/#using-the-microdata-dom-api Microdata DOM APIでHTMLからデータを抽出できる • Available in JavaScript: https://github.com/termi/Microdata-JS • There are also some specs for translating Microdata into JSON MicrodataからJSONに変換もできる • HTML’s great advantage is that it has links and forms built-in HTMLはリンクとフォームを持っているのが大きなアドバンテージ
  • 33. But you probably want a JSON Web API… でもたぶんJSON Web APIが欲しいよね data link form HTML +Microdata ✓✓ ✓ ✓ JSON ✓ - - ✓✓: including “meaning of data” • You have to fill in links and forms (also the meanings of data, if possible) リンクとフォームを埋めればいい(できればデータの意味も)
  • 34. Links and Forms in JSON • Use a JSON-based format that can represent links and forms • There are other formats Siren, Collection+JSON, Mason, Verbose, etc data link form JSON ✓ - - JSON +Link header ✓ ✓ - HAL ✓ ✓ - JSON-LD ✓✓ ✓ - JSON-LD +Hydra ✓✓ ✓ ✓ UBER ✓ ✓ ✓ リンクとフォームを表現できる JSONベースのフォーマットがある ✓✓: including “meaning of data”
  • 36. Hypermicrodata gem https://github.com/tkawa/hypermicrodata • Translate HTML into JSON on Server-side • Extract not only Microdata but also links and forms from HTML • Generate a JSON-based format that naturally fits with an explanation of meaning of data サーバサイドでHTMLをJSONに変換 Microdataだけではなく リンクとフォームもHTMLから抽出 データの意味も表しやすい形で JSONベースのフォーマットを生成
  • 37. Design procedure in Rails with Hypermicrodata gem Hypermicrodata gemを使ったRailsによる設計手順 1. Design resources 2. Draw a state diagram 3. Connect names of data with corresponding URLs 4. Write HTML templates (Haml, Slim, etc) with Microdata markup 1. リソース設計 2. 状態遷移図を描く 3. データの名前を対応するURLに結びつける 4. HTMLテンプレートを書き Microdataでマークアップ (Then, write profiles and explanations that are not defined in schema.org, if necessary)
  • 38. 1. Design resources column name short description type text content text of note text published_at published time of note datetime (id, created_at, updated_at) (auto-generated) $ rails g model Note text:text published_at:datetime model: Note controller: NotesController routing: resources :notes
  • 39. 2. Draw a state diagram Begin with Collection & Member Resource pattern of Rails (API ver.) item collection Collection Member create*† update*, delete* * unsafe † non-idempotent
  • 40. Collection of Note Note (text, published_at, created_at, updated_at, id) item collection create*† update*, delete*, * unsafe † non-idempotent publish* next, prev Home notes home
  • 41. 3. Connect names of data with corresponding URLs Collection of Note http://schema.org/ItemList Note http://schema.org/Article text http://schema.org/articleBody published_at http://schema.org/datePublished created_at http://schema.org/dateCreated updated_at http://schema.org/dateModified id (No need because each note has its own URL) Home http://schema.org/SiteNavigationElement
  • 42. 4. Write HTML templates with Microdata Collection of Note %div{itemscope: true, itemtype: 'http://schema.org/ItemList', itemid: notes_url, data: {main_item: true}} - @notes.each do |note| = link_to note.text.truncate(20), note, rel: 'item', itemprop: 'hasPart' /app/views/notes/index.html.haml GET /notes HTTP/1.1 Host: www.example.com Accept: application/vnd.amundsen-uber+json = form_for Note.new do |f| = f.text_field :text = f.submit rel: 'create' { "uber": { "version": "1.0", "data": [{ "url": "http://www.example.com/notes", "name": "ItemList", "data": [ { "name": "hasPart", "rel": "item", "url": "/notes/1" }, { "name": "hasPart", "rel": "item", "url": "/notes/2" }, { "rel": "create", "url": "/notes", "action": "append", "model": "note%5Btext%5D={text}" }, { "rel": "profile", "url": "/assets/note.alps"} ] }] } } Link Form
  • 43. %div{itemscope: true, itemtype: 'http://schema.org/Article', itemid: note_url(@note), data: {main_item: true}} /app/views/notes/show.html.haml %span{itemprop: 'articleBody'}= @note.text %span{itemprop: 'datePublished'}= @note.published_at %span{itemprop: 'dateCreated'}= @note.created_at %span{itemprop: 'dateModified'}= @note.updated_at = form_for @note, method: :put do |f| = f.text_field :text = f.submit rel: 'update' = button_to 'Destroy', @note, method: :delete, rel: 'delete' = button_to 'Publish', publish_note_path(@note), rel: 'publish' unless @note.published? = link_to 'Next note', note_path(@note.next), rel: 'next' if @note.next = link_to 'Prev note', note_path(@note.prev), rel: 'prev' if @note.prev = link_to 'Collection of Note', notes_path, rel: 'collection', itemprop: 'isPartOf' GET /notes/1 HTTP/1.1 Host: www.example.com Accept: application/vnd.amundsen-uber+json Note { "uber": { "version": "1.0", "data": [{ "url": "http://www.example.com/notes/1", "name": "Article", "data": [ { "name": "articleBody", "value": "First note's text" }, { "name": "datePublished", "value": null }, { "name": "dateCreated", "value": "2014-09-11T12:00:31+09:00" }, { "name": "dateModified", "value": "2014-09-11T12:00:31+09:00" }, { "name": "isPartOf", "rel": "collection", "url": "/notes" }, { "rel": "update", "url": "/notes/1", "action": "replace", "model": "note%5Btext%5D={text}" }, { "rel": "delete", "url": "/notes/1", "action": "remove" }, { "rel": "publish", "url": "/notes/1/publish", "action": "append" }, { "rel": "next", "url": "/notes/2" }, { "rel": "profile", "url": "/assets/note.alps" } ] }] } }
  • 44. %div{itemscope: true, itemtype: 'http://schema.org/Article', itemid: note_url(@note), data: {main_item: true}} %span{itemprop: 'articleBody'}= @note.text %span{itemprop: 'datePublished'}= @note.published_at %span{itemprop: 'dateCreated'}= @note.created_at %span{itemprop: 'dateModified'}= @note.updated_at = form_for @note, method: :put do |f| = f.text_field :text = f.submit rel: 'update' = button_to 'Destroy', @note, method: :delete, rel: 'delete' = button_to 'Publish', publish_note_path(@note), rel: 'publish' unless @note.published? = link_to 'Next note', note_path(@note.next), rel: 'next' if @note.next = link_to 'Prev note', note_path(@note.prev), rel: 'prev' if @note.prev = link_to 'Collection of Note', notes_path, rel: 'collection', itemprop: 'isPartOf' Note = button_to 'Publish', publish_note_path(@note), = link_to 'Next note', note_path(@note.next), = link_to 'Prev note', note_path(@note.prev), { "uber": { rel: 'publish' unless @note.published? rel: 'next' if @note.next rel: 'prev' if @note.prev "version": "1.0", "data": [{ "url": "http://www.example.com/notes/1", "name": "Article", "data": [ explanation of restriction Now you can publish, but cannot go prev { "name": "articleBody", "value": "First note's text" }, { "name": "datePublished", "value": null }, { "name": "dateCreated", "value": "2014-09-11T12:00:31+09:00" }, { "{ rel": "name": "publish", "dateModified", "url": "value": "/"2014-notes/09-11T12:1/publish", 00:31+09:00" }, "{ action": "name": "isPartOf", "append" "rel": }, "collection", "url": "/notes" }, { "rel": "update", "url": "/notes/1", "action": "replace", { "rel": "model": "next", "note%5Btext%"url": 5D={text}" "/notes/}, 2" }, { "rel": "delete", "url": "/notes/1", "action": "remove" }, { "rel": "publish", "url": "/notes/1/publish", "action": "append" }, { "rel": "next", "url": "/notes/2" }, { "rel": "profile", "url": "/assets/note.alps" } ] }] } }
  • 45. 3 Pros of this design procedure • DRY • When providing both HTML and JSON • Awareness of links and forms • Framing the API as an HTML Web app gets you focused on these state transition • Constraints • “Constraints are liberating” この設計手順の3つのメリット HTMLとJSON両方提供するならDRY APIをWebアプリと同じように考えることで状態遷移に着目し リンクとフォームを意識できる 「制約は自由をもたらす」
  • 46. If you want to write only JSON, you should keep in mind もしJSONだけを書くときは注意すること • To stay focused on the link/form pattern: • Draw a state diagram リンク・フォームを意識するために 状態遷移図を描きましょう • To keep your API decoupled: • Use view templates or representers such as Jbuilder/RABL instead of model.to_json 疎結合のために、model.to_jsonはやめて ビューテンプレートを使いましょう • Use a JSON-based format with links and forms リンクとフォームを持ったJSONベースのフォーマットを使いましょう • In addition, it is better to use standard names such as schema.org schema.orgのような標準名を使うとさらに良いです
  • 47. “WebアプリとWeb APIを分けて考えない” “Don’t consider Web app and Web API separately” – 「Webを支える技術」@yohei
  • 48. Conclusion: Design Your Web API the same way as an HTML Web App 結論: Web APIはHTML Webアプリと同じように設計しよう • A Web API is nothing special, It just has a different representation format Web APIは特別なものではなく、ただ表現フォーマットが違うだけ • Awareness of state transitions by drawing a diagram will remind you of links and forms 状態遷移図を描いて状態遷移を意識することで、リンクやフォームを忘れずにすむ
  • 49. Finally • Unfortunately, no de-facto standard JSON format, client implementations, libraries, etc 残念ながら、デファクトスタンダードがない • We can do better by focusing on the principles and constraints of REST RESTの制約・原則を意識するともっとうまくできる • Hypermedia is one of the most important elements of REST, and a key step toward building Web APIs adaptable to change ハイパーメディアはRESTの最も重要な要素で 変化に適応できるWeb APIへの重要なステップ
  • 50. Build a Better & Adaptable Web API. Thank you for your attention. References • L. Richardson & M. Amundsen “RESTful Web APIs” (O’Reilly) • 山本陽平 “Webを支える技術” (技術評論社) • Designing for Reuse: Creating APIs for the Future http://www.oscon.com/oscon2014/public/schedule/detail/34922 • API Design Workshop 配布資料 http://events.layer7tech.com/tokyo-wrk • https://speakerdeck.com/zdne/robust-mobile-clients-v2 • http://www.slideshare.net/yohei/webapi-36871915 • http://smizell.com/weblog/2014/solving-fizzbuzz-with-hypermedia • 山口 徹 “Web API デザインの鉄則” WEB+DB PRESS Vol.82