4章
リソース指向アーキテクチャ(ROA)
2008/05/10 第2回RESTful本読書会
岩本隆史<hello@iwamot.com>
4.1 なぜリソース指向という
用語を作るのか
4.1 なぜリソース指向という用語を作るのか
Q. 単にRESTじゃダメなの?
A. ダメ。理由は3つ。
4.1 なぜリソース指向という用語を作るのか
A. まず、RESTはアーキテクチャではない。だから、本書で提案するアーキテクチャをRESTとは呼べない。
Q. …アーキテクチャって?
4.1 なぜリソース指向という用語を作るのか
A. 明確な定義こそないものの、本書では「アーキテクチャ」を「基本設計」の意味で使っている。RESTは基本設計ではなく、一連の設計条件だ(ULCODC$SS)。
4.1 なぜリソース指向という用語を作るのか
- 【ROA】
- RESTという設計条件をなるべく満たす(=RESTfulな)Webサービスの基本設計のこと。
4.1 なぜリソース指向という用語を作るのか
Q. 用語を作る理由の2つめは?
A. ROAは、RESTの空白部分を補うものだから、RESTとは呼べない。
Q. kwsk
4.1 なぜリソース指向という用語を作るのか
- RESTの定義には空白部分が多い
- 空白部分は実装者が慣習で補ってきた
(オレオレRESTful Webサービスの跋扈)
- 明確なベストプラクティスで慣習を置き換えるのが本書の目的
- RESTとは別物になるため、同じ名前で呼ぶのは公正ではない
4.1 なぜリソース指向という用語を作るのか
A. 最後の理由。「REST」は宗教戦争用語だから、使いたくない。
Q. mjsk
4.1 なぜリソース指向という用語を作るのか
- 様々なRESTfulアーキテクチャの支持者が繰り広げる「正しさ戦争」に巻き込まれたくない
- 「REST」の冠を外すことで、ROAに賛同できない人が「あんなの元々RESTfulじゃないからね」といえるようになる
Q. おとなの知恵だな…
4.1 おわり
4.2 リソースとは何か
4.2 リソースとは何か
Q. ちょっと待った! なんでいきなりリソースの話になるの? そりゃROAだからResourceの話が出るのは分かるけど、「RESTfulなWebサービスの基本設計」が「リソース指向」になる脈略が分からない。
4.2 リソースとは何か
A. Roy Fieldingの論文は読んだかい? 「5.2.1 Data Elements」に「REST components communicate by transferring a representation of a resource」とある。
4.2 リソースとは何か
A. つまり、「REpresentational State Transfer」(REST)の「State」とは、「リソースの状態」のことなんだ。
Q. なるほど。じゃあ、リソースの定義を教えれ。
4.2 リソースとは何か
- それ自体を参照するに値するほどの重要性を持つもの(参照したい、リンクしたい、コメントしたい、更新/削除したい…)
- アルゴリズムの実行結果もリソース(検索結果など)
- コンピュータ上に格納することができ、一連のビットで表せるもの
4.2 おわり
4.3 URI
4.3 URI
Webにおいて、リソースがリソースであるためには、URIを少なくとも1つは持っていなければならない。
4.3.1 URIは記述的であるべき
4.3.1 URIは記述的であるべき
- 【記述的】
- リソースとURIを直感的に対応させること。
- 例:/search/Jellyfish
- ○:/search/Mice
- ×:/i-want-to-know-about/Mice
4.3.1 URIは記述的であるべき
- 利点:サービスのURIの構造を知っているクライアントが、サービスへのエントリポイントを独自に作成できる
- 筆者の推奨事項(RESTのルールではない)
4.3.2 URIとリソースの関係
4.3.2 URIとリソースの関係
- リソースはURIを1つ以上持つことができる(例:1.0.3.tar.gz=latest.tar.gz)
- リソースが複数のURIを持つと、個々のURIの価値が希薄化する(例:SBMのブックマークが分散)
4.3.2 URIとリソースの関係
希薄化を回避するには、1つのURIを正規URIとし、非正規URIへのアクセス時に下記いずれかの処理を行う。
- 「Location」ヘッダで正規URIを返し、「303 See Other」とする
- 「Content-Location」ヘッダで正規URIを返す
4.3 おわり
4.4 アドレス可能性
4.4 アドレス可能性
- 【アドレス可能性】
- アプリケーションがそのデータセットの重要な部分をリソースとして公開していること。
4.4 アドレス可能性
Q. 先生! その「アドレス可能性」は、RESTのどの設計条件から導けるんですか?
A. 「ULCODC$SS」の「$」(Cache)制約から導けるという理解で良いんじゃないだろうか。
4.4 アドレス可能性
- アドレス可能だからこそ、URIを本に掲載したり、ブックマークしたり、リンクしたり、キャッシュ($)したりできる
- 多くのAjaxアプリケーションはアドレス可能でない(例:Gmail。APIはアドレス可能だが、ユーザの見ている画面はアドレス可能でない)
4.4 おわり
4.5 ステートレス性
4.5 ステートレス性
- 【ステートレス性】
- すべてのHTTPリクエストが完全に分離していること。
- RESTの設計条件「ULCODC$SS」のひとつ。
4.5 ステートレス性
ステートフルな例
- /search?q=mice
- start=10
- サーバが「/search?q=mice」を維持する必要がある
- FTPはステートフル(例:作業ディレクトリを維持)
4.5 ステートレス性
ステートレスな例
- /search?q=mice
- /search?q=mice&start=10
- リクエスト間に依存性がないため、それぞれを異なるサーバで処理できる(負荷の分散)
4.5 ステートレス性
セッションIDをCookieやURIに埋め込むと、ステートレス性が無効(ステートフル)になる。
- セッションIDは状態ではない(状態へのキー)
- サーバがセッション状態を維持する必要がある
- 岩本補足:セッションIDを含むリクエストは、セッション開始リクエストに依存している
4.5.1 アプリケーション状態と
リソース状態
4.5.1 アプリケーション状態とリソース状態
- 「状態」は、クライアントが維持すべき「アプリケーション状態」と、サーバーが維持すべき「リソース状態」に分けられる
- クライアントがアプリケーション状態を維持しているのがステートレス
- サーバーがアプリケーション状態を維持しているのがステートフル
4.5.1 アプリケーション状態とリソース状態
アプリケーション状態
- クライアントごとに異なる状態
- 例:検索エンジンのクエリ文字列やページ番号
- クライアントがリクエストを送信する際には、サーバーがリクエストを処理するために必要なアプリケーション状態をすべて含めなければならない
4.5.1 アプリケーション状態とリソース状態
リソース状態
- すべてのクライアントで同じ状態
- 例:Flickrの画像
4.5.1 アプリケーション状態とリソース状態
アプリケーション状態をサーバーが維持するケース
- Google SOAP検索APIのアプリケーションキーは、1日につき1000個のリクエストに対して有効
- クライアントごとに異なるためアプリケーション状態
- 「○回目の呼び出しです」というクライアントの申告は信用できない → サーバーで維持 → ステートフル
- 絶望リストに「APIキーでリクエスト数を制限する場合、ステートフルになるのは仕方ない」が追加されました
4.5 おわり
4.6 表現
4.6 表現
サーバーはリソースを特定のファイル形式と特定の言語で送信しなければならない。このときのファイル形式や言語のことを「表現」と呼ぶ。
4.6.1 表現の選択
4.6.1 表現の選択
プレスリリースに日本語版と英語版があるケース
A. 個別のURIを割り当てる方法(著者推奨)
- http://example.com/releases/104.ja
- http://example.com/releases/104.en
- URIの希薄化が問題になる
- 言語非依存(プラトニック形式)のリソースを提供することで緩和(http://example.com/releases/104)
4.6.1 表現の選択
プレスリリースに日本語版と英語版があるケース
B. コンテンツネゴシエーションを使う方法
- プラトニック形式のリソースのみ提供
- Accept-Languageリクエストヘッダで表現を選択
- HTMLバリデータなどのプログラムへURIを引き渡すことを考えると、個別のURIを割り当てるほうが有用
4.6.1 表現の選択
言語以外にも表現の選択に使われるメタデータがある。
- ファイル形式(Acceptリクエストヘッダ)、決済情報、認証情報、リクエスト時間、キャッシュディレクティブ、クライアントのIPアドレス
- なるべくURIに入れることを推奨
4.6 おわり
4.7 リンクと接続性
4.7 リンクと接続性
- 【接続性】
- リソース同士が相互にリンクされていること。
- リンクをたどったり、フォームを送信したりするだけで他のリソースへアクセスできるのは、接続性のおかげ。
4.7 リンクと接続性
Q. 先生、ごぶさたです! その「接続性」は、RESTのどの設計条件から導けるんですか?
A. 「ULCODC$SS」の「L」(Layered)制約から導けるという理解で良いと思う。接続性が低ければ、クライアントがサーバのURI構成を知っている必要がある。「システムの知識を単一階層に限る」のがLayered制約。
4.7 リンクと接続性
Amazon S3のバケットリストは接続性が低い
- 返されるXML内にバケットのURIが欠けている
- バケットURIの構築ルールをクライアントが知っている必要がある
4.7 おわり
4.8 統一インターフェイス
4.8.1 GET、PUT、DELETE
4.8.1 GET、PUT、DELETE
- GET:リソースの取得
- PUT:リソースの作成または変更
- DELETE:リソースの削除
4.8.2 HEADとOPTIONS
4.8.2 HEADとOPTIONS
- HEAD:メタデータ固有の表現を取得
- OPTIONS:特定のリソースがサポートするHTTPメソッドを調べる
- 「Allow: GET, HEAD」
- リクエストヘッダ(Authorizationなど)の内容で結果が変わることもある
4.8.3 POST
4.8.3 POST
従属リソースの作成
- 従属リソースとは、「親」リソースに関連して存在するリソースのこと
- POST /weblogs/myweblog
→ /weblogs/myweblog/entries/1000
- 「POST(a)」と呼ばれる(aはアペンド)
- 従属リソースのURIをクライアントが決められる場合はPUTを使う
4.8.3 POST
リソース状態へのアペンド
- 「/log」というリソースのみを提供するイベントログサービスにログを追加したい
- POST /log
→ データが追加される
- 従属リソースの作成時とPOSTの意味は同じ(新しいリソースができるか否かの違い)
4.8.3 POST
オーバーロードPOST:統一性の低いインターフェイス
- 「従属リソースの作成」でも「リソース状態のアペンド」でもないPOST(XML-RPC的)
- 「従属リソースの作成」と「リソース状態のアペンド」の両方をサポートするリソースがある場合、採用せざるをえない(どちらのPOSTかを指定するメソッド情報が必要)
- 「POST(p)」と呼ばれる(pはプロセス)
4.8.4 安全性とべき等性
4.8.4 安全性とべき等性
安全性
- リクエストによってサーバー状態が変更されないこと
- GET、HEADは正しく使用すれば安全
- 1を掛けるようなもの(4×1×1×1)
- ヒットカウンタがインクリメントされる程度の副作用なら可(クライアントが副作用をあてにしたり、リクエストしたことを後悔するなら不可)
4.8.4 安全性とべき等性
べき等性
- 1つのリクエストを何度繰り返しても同じであること
- GET、HEAD、PUT、DELETEは正しく使用すればべき等
- 0を掛けるようなもの(4×0×0×0)
4.8.4 安全性とべき等性
安全性とべき等性はなぜ重要なのか
- 信頼できないネットワーク経由でも安心(レスポンスがなければもう1回送ればよい)
- POSTは安全でもべき等でもない(繰り返されると結果が読めない)
- 思いつき:重要な処理をPOSTにまかせるのは怖い。ショッピングサイトの場合、買い物かごリソースをPOSTで作成、購入確定フラグをPUTで立てるのはどうか?
4.8.5 統一インターフェイスは
なぜ重要なのか
4.8.5 統一インターフェイスはなぜ重要なのか
- 統一インターフェイスがなければ、サービスごとに情報を送受信する方法を習得しなければならない
- GETとオーバーロードPOSTのみで構成されるサービスも、統一インターフェイスを守っているという意味ではRESTfulだが、ROAには準拠しない
4.8 おわり
4.9 まとめ
4.9 まとめ
ROAに登場する概念
- リソース
- 名前(URI)
- 表現
- リソース間のリンク
4.9 まとめ
ROAのもつ特性
- アドレス可能性
- ステートレス性
- 接続性
- 統一インターフェイス
4.9 おわり