HATEOAS

REST API のレスポンスにリンクを含め、クライアントが次に取れるアクションを動的に発見できるようにする設計原則

API

HATEOAS とは

HATEOAS (Hypermedia As The Engine Of Application State) は、REST アーキテクチャの制約の 1 つで、API のレスポンスに「次に取れるアクション」へのリンクを含める設計原則である。クライアントは URL をハードコードせず、レスポンスに含まれるリンクをたどって操作を進める。

Roy Fielding が 2000 年の博士論文で REST を定義した際、HATEOAS は REST の必須要素として位置づけられた。しかし実際には、HATEOAS を完全に実装している API は少数派だ。Richardson の REST 成熟度モデルではレベル 3 (最高レベル) に位置する。

具体例

注文リソースを例に、リンクを載せると何が変わるのかを見る。

// 注文の取得レスポンス (HATEOAS なし)
{
  "orderId": "ORD-123",
  "status": "pending",
  "total": 5000
}

// 注文の取得レスポンス (HATEOAS あり)
{
  "orderId": "ORD-123",
  "status": "pending",
  "total": 5000,
  "_links": {
    "self": { "href": "/orders/ORD-123" },
    "cancel": { "href": "/orders/ORD-123/cancel", "method": "POST" },
    "payment": { "href": "/orders/ORD-123/payment", "method": "POST" }
  }
}

statusshipped に変わると、cancel リンクが消え、track リンクが出現する。クライアントはリンクの有無で「今キャンセルできるか」を判断できる。ビジネスロジックの判断がサーバー側に集約される。

この例で使った _links は HAL (Hypermedia Application Language) の書き方に寄せたものだが、method は HAL が定義するフィールドではない。HAL のリンクオブジェクトに用意されているのは href / templated / type / deprecation / name / profile / title / hreflang で、HTTP メソッドを伝える場所が無い。メソッドまでレスポンスに載せたいなら、動作 (action) を表現できる Siren のような形式を選ぶか、「cancel は POST」のようにリンク関係名とメソッドの対応をクライアントと事前に取り決めることになる。

HATEOAS のメリット

クライアントとサーバーの疎結合

クライアントが個々の URL をハードコードしないため、サーバー側で URL 構造を変更してもクライアントの修正が不要になる。/api/v1/orders/api/v2/orders に変更しても、クライアントはレスポンスのリンクをたどるだけだ。

ただし結合がなくなるわけではなく、依存先が移るだけだと理解しておきたい。クライアントは入口となる URL を依然として知っている必要があり、そこから先は cancelpayment といったリンク関係名と、レスポンスの構造に依存する。関係名を改名すればクライアントは同じように壊れる。つまり HATEOAS で守れるのは URL の自由度であり、その代償として「関係名は URL より変えにくい」という制約を引き受けることになる。関係名は業務の操作名でなく、意味の変わりにくい語で設計しておく。

状態遷移の明示

「この注文は今キャンセルできるか」をクライアントが自前で判断する必要がない。cancel リンクが存在すればキャンセル可能、存在しなければ不可能。UI のボタンの表示/非表示をリンクの有無で制御できる。

API の自己記述性

レスポンスを見るだけで、次に何ができるかが分かる。API ドキュメントを参照しなくても、リンクをたどることで API の全機能を発見できる (理論上は)。

HATEOAS を採用しない理由

実務では HATEOAS を完全に実装しないケースが多い。その理由を理解しておくことが重要だ。

実装コストが高い

すべてのレスポンスにリンクを含めるには、各リソースの状態に応じて動的にリンクを生成するロジックが必要だ。単純な CRUD API に対してはオーバーエンジニアリングになりやすい。

フロントエンドとの相性

SPA (Single Page Application) やモバイルアプリでは、画面遷移のロジックがクライアント側にある。サーバーが返すリンクに従って画面遷移するモデルは、現代のフロントエンド開発と噛み合わない場面がある。

標準フォーマットの乱立

HATEOAS のリンク形式には HAL、JSON:API、Siren、JSON-LD など複数の標準が存在し、統一されていない。どれを採用するかの判断コストが発生する。

実務での落としどころ

完全な HATEOAS を実装しなくても、部分的に取り入れることで恩恵を得られる。

  • ページネーション: nextprevfirstlast といったリンク関係でページ間を移動させる。GitHubREST API はこれをレスポンス本文ではなく HTTP の link ヘッダー (rel="next"rel="last" 等) で返している。本文に入れるかヘッダーに入れるかは選択の余地があり、関係名でページを渡す発想自体は広く普及している。一方で不透明な継続トークン (AWS の API が返す NextToken 型) を渡す設計も一般的で、こちらはリンクをたどるモデルではない
  • 関連リソース: 注文レスポンスに customeritems へのリンクを含め、クライアントが必要に応じて取得できるようにする
  • 状態遷移: 注文のステータスに応じて、可能なアクション (cancelrefund) のリンクを動的に返す

HATEOAS vs 通常の REST

HATEOAS と通常の REST の違いを以下にまとめる。

観点通常の RESTHATEOAS
リンククライアントが URL を構築サーバーがリンクを提供
結合度URL 構造に依存リンクに従うだけ
発見可能性API ドキュメントが必要レスポンスから発見
実装コスト低い高い
採用率高い低い

さらに掘り下げるなら関連書籍が参考になる。

この記事は役に立ちましたか?

関連用語

関連する記事