Skip to content

Instantly share code, notes, and snippets.

@tkawa
Last active April 5, 2016 09:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkawa/090cfa746029b4bfae17fcf42959d351 to your computer and use it in GitHub Desktop.
Save tkawa/090cfa746029b4bfae17fcf42959d351 to your computer and use it in GitHub Desktop.
RESTful#とは勉強会14

RESTful#とは勉強会14 2016-04-05

質問はTwitterへ #RESTudy をつけてどうぞ。

「Webを支える技術」読書会

第11章〜第13章は、考え方としては役立ちますが、現在ほとんど使われていない記述があるので、後回しにしてまず第14章から読んでいきましょう。14章を読み終わったら、グループで話し合って第11章〜第13章の興味のあるところに進んでもらってかまいません。

第14章 JSON

14.1 JSONとは何か (p.231)

JSONはJavaScript Object Notationの略で、RFC 4627が規定するデータ記述言語です。

現在は更新され、RFC7159で規定されています。ECMA-404でも規定されています。

数値

JavaScriptの仕様となっていることもあり、JSONの数値はIEEE 754-2008 binary64 (浮動小数点数演算標準-倍精度) で実装されていることが多いので、その範囲外の 1E4003.141592653589793238462643383279 などの JSON 数を使うと相互運用性の問題が生じるかもしれません。整数は [-(2**53)+1, (2**53)-1] の範囲以外は問題が生じるかもしれません。

14.5 JSONPによるクロスドメイン通信

Ajax で用いる XMLHttpRequest という JavaScript のモジュールは、セキュリティ上の制限から JavaScript ファイルを取得したのと同じサーバとしか通信できません。

とありますが、現在の多くのブラウザでは XMLHttpRequest Level 2 でCORSに対応したため、クロスドメイン通信が可能になっています。

CORS (Cross-Origin Request Sharing)

web サーバーがサイトを跨ぐアクセスを制御する方法を規定することで、サイト間での安全な通信を保証するというものです。特筆すべき点として、この仕様は XMLHttpRequest のような API コンテナ内で緩和策として使用されることにより、現行のブラウザにおいて同一ドメイン制限を超えることを可能にするということです。

https://developer.mozilla.org/ja/docs/HTTP_access_control

ブラウザからJavaScriptで他のサーバにアクセスしようとしたとき、昔は同じドメインにしかアクセスできませんでした。(「クロスドメイン通信の制限」p.237を参照) CORSを使うと、 サーバが許可した場合 ブラウザは別ドメインのサーバへJavaScriptでアクセスすることができます。デフォルトでは不許可です。

サーバがブラウザへ許可を伝える方法はレスポンスヘッダですが、POSTのような安全でないメソッドの場合、レスポンスで許可/不許可を確認する前に、すでに安全でない操作が完了してしまいます。これではデフォルトで不許可になりません。

そこで、先にサーバの許可/不許可を確認するため、ブラウザは自動的にOPTIONSリクエストを送ります。これをプリフライト(preflight: 飛行前の)リクエストといいます。

この用途ではサーバはAllowヘッダではなくAccess-Control-Allow-Origin,Access-Control-Allow-Methodsヘッダなどを返します。

POST http://other.example.jp/resources/post-here/ のためのプリフライトリクエストとレスポンスの例

OPTIONS /resources/post-here/ HTTP/1.1
Host: other.example.jp
Origin: http://me.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Access-Control-Allow-Origin: http://me.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000
...

許可されたので、この後ブラウザはPOSTリクエストを送ります。

利用例

Amazon S3にブラウザからJavaScriptで直接アップロードすることができます。

第11章〜第13章

第11章 microformats はほとんど使われていません。

microformats では class 属性や rel 属性の値だけでメタデータを特定するため、もしたまたま同じ値の class 属性や rel 属性を持った Web ページがあっ た場合、プログラムが誤判定を起こしたり、同じ属性値を持った別の microformats が作れなくなったりするのです。

— 「Webを支える技術」p.184 より

この問題点をHTML5の専用属性を作ることで解決し、現在代わりに使われているのが Microdata です。また、あまり使われていませんが RDFaの複雑さを緩和した RDFa Lite もあります。

第12章 Atom は、RSSも含む「フィード」という枠組みでは少し使われています。コレクションリソースの考え方は設計のとき重要です。 12.5節「Atomの拡張」はOpenSearch以外はほとんど使われていません。

第13章 Atom Publishing Protocol は、一時期GoogleがAtomPubを拡張したGDataを多くのWeb APIに採用し、Microsoftも同様に拡張したODataを使用したりしていましたが、次第に単純なJSONのAPIに移っていき、今はほとんど使われていません。

復習「RESTful Web アプリの設計レビューの話」

http://www.slideshare.net/t_wada/restful-web-design-review

スライドを読んで、感じたこと、疑問点などをグループで話し合いましょう。 スライド中の用語に関して理解が不安なときは「Webを支える技術」のページを振り返ってみましょう。

前回のおさらい&ポイント解説

p.15 CRUD の重力に引かれていないか

リソースの GET/POST/PUT/DELETE と DBの SELECT/INSERT/UPDATE/DELETE は単純に対応させてしまいがちですが(とくにWeb APIの設計では注意)、「情報アーキテクチャからの導出」(Webを支える技術 p.305-)に沿って画面から考えると、従属的なテーブル、粒度の細かいテーブルはリソースに現れにくくなります。

例えば tagging テーブルに“自動的に”対応する taggings リソースを作ったとします。 /taggings, /taggings/1 のような画面は必要かどうかを考えてみましょう。

p.16 CRUD の重力に引かれていないか

リソースの粒度/視点(つまりは URL)とデータベースの粒度/視点の違いを解釈してしかるべく結びつけるのが Controller の仕事

リソースはモデルに対応するのではなくコントローラに対応します。リソースとデータベースを直結するのは失敗の原因になります。

p.17 HTTP メソッドの選択

GET 重要。とても重要。

意外と無視されていることが多いですが、とても重要です。ブラウザにURLを入力してEnterを押すと、GETになります。つまりGETはデフォルトのメソッドです。POSTだけ有効でGETできないようなリソースを作ってはいけません。

POSTとPUTの違いは、Webを支える技術 p.95 を参考にしましょう。

POST でリソースを作成する場合、クライアントはリソースの URI を指定できません。URI の決定権はサーバ側にあります。逆に PUT でリソースを作成する場合、リソースの URI はクライアントが決定します。

_

どうにもならなくなったら POST に倒す

これはWebを支える技術 p.92 を参考にしましょう。 ただし「どうにもならなくなったら」は最終手段です。その前に、CRUDに当てはまらないと思えるような処理は、別のリソースに分けた方がうまくいくことが多いです。

HTTP メソッドでは実現できない機能があると感じたら、それが独立した別リソースで代替できないかを考える。検索機能を実現する SEARCH メソッドを HTTP に追加するのではなく、「検索結果リソース」を GET する、と考えることが重要である

— 「Webを支える技術」p.295 より

例:ユーザをグループに追加・グループから削除したい

POST /groups/1/add_user POST /groups/1/remove_user ?
POST /users/1/join_group POST /users/1/leave_group ?
membershipというリソースをつくることで POST /memberships DELETE /memberships/3 とできる。

ここまでの内容は、@moroさんの「RESTful APIのみつけかた」もとても参考になります。

REST復習の参考スライド

「Webを支える技術」も活用しましょう。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment