世界を動かす技術を、日本語で。

ほとんどのRESTful APIは実際にはRESTfulではない

概要

  • RESTは Roy Fieldingの論文 で提唱された アーキテクチャスタイル
  • RESTの本質は スケーラビリティ・シンプルさ・適応性 の追求
  • HATEOAS(ハイパーメディア駆動) がRESTの重要な原則
  • リソースは URIで一意に識別される抽象概念
  • RESTful APIと呼ぶには 厳格なルールと制約 が存在

RESTの本質とFielding論文の要点

  • RESTは “Representational State Transfer” の略称、 ネットワーク型システム設計 のためのスタイル
  • “Architectural Styles and the Design of Network-based Software Architectures” (2000年、Roy T. Fielding著)で初めて体系化
  • RESTは スケーラビリティ、パフォーマンス、保守性 を重視した設計指針
  • Webサービス設計 における 分散システムの成功要因 としてREST原則を紹介
  • RESTは HTTPメソッドやCRUD に限定されず、 原則と制約 の集合体

RESTの誤解と正しい理解

  • REST=CRUDRESTful APIは動詞禁止 などの俗説は誤り

  • RESTの本質は ハイパーメディア(HATEOAS) による状態遷移の駆動

  • “REST APIs must be hypertext-driven.” (Fielding, 2008年)という明確な主張

  • ハイパーメディア制御 は、リソース表現内に次のアクションを案内するリンクや操作情報を埋め込む仕組み

  • クライアントとサーバーの 疎結合進化可能性 の確保が目的

    • 例:
      {
        "orderId": 123,
        "_links": {
          "self": { "href": "/orders/123" },
          "cancel": { "href": "/orders/123/cancel", "method": "POST" }
        }
      }
      

RESTにおける「リソース」とは

  • RESTにおけるリソースは URIで識別可能なあらゆる情報単位
  • 物理オブジェクト、概念、ドキュメント、サービス、抽象的なもの までも含む
  • リソースは サーバー上のエンティティそのものではなく、抽象的なマッピング
  • RFC 3986 も「リソースはURIで識別できるすべてのもの」と定義
  • 例:電子文書、画像、サービス、人物、企業、数値、関係タイプなど

FieldingによるRESTful APIの条件

  • HTTPベースなら何でもREST API という誤解をFielding自身が批判

  • RESTful APIと呼ぶための 6つのルール を提示

    1. 単一プロトコル依存の排除
      • URIによる識別は HTTP固有でなく、URI全般 で成り立つべき
    2. プロトコルの拡張・改変の禁止
      • HTTP標準の範囲内で動作、 独自拡張や仕様破壊は禁止
    3. URI設計よりメディアタイプ重視
      • リソース表現のフォーマットやリンク設計 に注力
      • URIやエンドポイントの構造記述は最小限に
    4. 固定リソース名・階層の否定
      • クライアントがURI構造を前提にしない設計
      • URI生成方法をサーバーが表現内で動的に指示
    5. 型付きリソースの排除
      • クライアントにとって重要なのは 表現のメディアタイプと標準化された関係名 のみ
    6. 初期URI以外の事前知識不要
      • 初期URIと標準メディアタイプ のみで利用開始
      • 以降の状態遷移はすべて サーバー提供のリンクや操作 によって誘導

REST設計ルールの解釈

  • 1. プロトコル依存の排除

    • URIは 資源の識別アクセス手段 を分離
    • URLはURIの一種 であり、API設計は HTTP固有に依存しない べき
  • 2. プロトコル変更の禁止

    • HTTP標準の厳守
    • 標準の曖昧部分は明確化してもよいが、 新たな意味付けや破壊的変更は禁止
  • 3. URIよりメディアタイプ設計

    • APIは データ表現形式(例:JSON, HTML)とリンク設計 に注力

    • URIの構造や操作のドキュメント化 よりも、 表現内のリンクや操作情報 の設計が重要

      • 例:
        {
          "name": "John Doe",
          "status": "inactive",
          "_links": { ... }
        }
        
  • 4. 固定リソース名・階層の否定

    • サーバー主導のURI生成 (HTMLフォームやURIテンプレートなど)
  • 5. 型付きリソースの排除

    • クライアントは 表現のメディアタイプとリンク関係名 のみを認識
  • 6. 初期URI以外の事前知識不要

    • 初期エントリーポイントURIと標準メディアタイプ だけで利用開始
    • 以降の状態遷移は サーバーからのリンク・操作案内 に従う

REST設計のまとめ

  • RESTは 単なるHTTP API設計手法ではなく、厳密なアーキテクチャスタイル
  • HATEOAS の実装がRESTful APIの鍵
  • URIで識別できるものはすべてリソース
  • メディアタイプ設計とハイパーメディア制御 に注力
  • 「RESTful API」と呼ぶには厳格な条件 があることを理解する必要

Hackerたちの意見

UIデザイナーは、ページの見た目を細かくコントロールしたいんだよね。例えば、リソースに対してできるアクションの中には大きなボタンで表示されるものもあれば、メニューに隠れてたり、UIに全く表示されないものもある。リソースでどんなアクションが可能かを全く知らないクライアントアプリケーションが、APIのレスポンスに基づいて動的に表示するだけだと、全部同じに見えちゃうんだよね。だから、この記事で説明されているRESTful APIは、フロントエンドUIを実装するという最も一般的なWeb APIの使い方にはあまり役立たないんだ。

「RESTful API」に関する俺の経験は、UIとはほとんど関係ない。UIだけが気になるなら、なんでAPIなんて必要なの?それならDWRみたいなサーバードリブンのクソに戻った方がいいんじゃない?

これは多くのレベルで間違ってる。 1. UXデザイナーは、製品の発見からローンチ後のサポート(UX仮説の検証)まで、ソフトウェア開発ライフサイクルのすべての段階で活動している。彼らはコントロールを行使するわけではなく、チームの一員として制約の中で働いている。UI内の特定のアクションの位置やそれをトリガーするインタラクションは、そのアクションの可用性とは無関係だ。可用性は状態によって定義される。状態が特定のアクションを制限する場合、UXはそれを反映する必要がある。 2. アーキテクチャの観点から見ると、状態チェックの動作をカプセル化すれば、次のように動作する: "if (state === something)" と "if (resource.links["action"] !== null)"。後者のアプローチの方がずっと良い。なぜなら、ほとんどの場合、状態を変更するアクションはサーバーでの検証を必要とし、そのロジックを一度(サーバー上で)だけ実装すればいいからだ。私はしばらくHATEOASアプリケーションを開発していて、HAL4Jライブラリを維持しているけど、このアプローチにはいくつかの複雑さがある。でも、UIデザインが問題の本質ではないことは確かだよ。

こういうAPIデザインが役立つのは、ユーザーがエージェント(例えばブラウザとか)を使ってAPIをナビゲートし、メディアタイプやリンクの名前に基づいて異なるレスポンスとやり取りできる場合だね。ほとんどのWeb APIはこの使い方を考慮して設計されてない。ユーザーに提示したい内容がもっと具体的なWebアプリをサポートするために設計されているんだ。これは意図的で価値のあることだよ。アプリのクリエイターは、自分のアプリの目標を達成するためにプレゼンテーションをコントロールできる必要があるからね。REST APIデザインは、ユーザーがAPIが提供するリソースとのやり取りをどうするかをコントロールすべきなケースに向いてる。REST APIデザインを使うべき例としては、- 法律コード、天気予報、不動産記録などの公にアクセス可能な情報のための政府ポータル - フォーム提出やその他のやり取りのための政府ポータル - WikipediaやOpenStreetmapのようなオープンデータイニシアティブ これらの例を考えると、「REST」の意味を厳格に守るのは学問的な人たちから来てるのが分かるし、定義に反対する人たちは特定のユーザー体験を作ろうとしているアプリ開発者が多い。解決策は簡単だよ:本当にRESTでない限り、RESTとは呼ばないこと。

法律コード、天気予報、不動産記録などの公にアクセス可能な情報のための政府ポータル そうそう、ちゃんと作られてるとすごくいいよね。 https://www.weather.gov/documentation/services-web-api

その通り、純粋なRESTはかなり学問的だよね。オープンデータやビッグデータに関わってきたけど、現実的なパフォーマンスやアプリアーキテクチャの設計にはいつも苦労してる。明白でないものについては、単純なイエス/ノーではなく、RESTの色合いがあると思う。学者たちも、いつかは実際に適用できる「アプリケーション」を作らなきゃいけないからね。

この種のAPIデザインが役立つのは、エージェント(例えばブラウザやそれに似たもの)を持つユーザーがいて、APIをナビゲートして、メディアタイプやリンクの名前に基づいて異なるレスポンスとやり取りできるときだよね。面白いことに、これってHTMLを完璧に説明してる。リンクが他のドキュメントに繋がってるドキュメントがあって、ユーザーはリンクの名前に基づいてナビゲートできる。ユーザーのために設計されてるなら、それはユーザーインターフェースって呼ばれるし、アプリケーションプログラミングのために設計されてるなら、それはアプリケーションプログラミングインターフェースって呼ばれる。だからHATEOASはちょっとバカバカしいと思う。APIはユーザーが直接使うべきだって思わせてるけど、もうそれはあるんだよね、UIって呼ばれてる。

この種のAPIデザインが役立つのは、エージェント(例えば、ブラウザやそれに類似したもの)を持つユーザーがAPIをナビゲートし、メディアタイプやリンクの名前に基づいて異なるレスポンスと対話できるときです。 > ほとんどのウェブAPIはこのユースケースを念頭に置いて設計されていません。APIがAIの消費をサポートするようになると、これが変わるのかな?発見可能性はAIにとって非常に重要で、ウェブアプリ開発者よりもずっと重要です。MCPはツールの発見可能性がどれほど強力であるかを示しています。HATEOSは、APIの消費に同様の利点をもたらすかもしれません。

この種のAPIデザインが役立つのは、エージェント(例えば、ブラウザやそれに類似したもの)を持つユーザーがAPIをナビゲートして、メディアタイプやリンクの名前に基づいて異なるレスポンスと対話できるときだ。ウェブページでないクライアントをプログラミングしているときにも役立つ!何かをGETして、返された表現のフィールドやパスを参照して、新しいURIを構築して、操作を実行する、みたいな感じ。ディレクトリやデータベースアプリケーションを考えてみて。RESTfulでHATEOASなAPIを定義して、それ用のシングルページウェブアプリケーションを作ったり、好みに応じて非SPAを作ったり、同じことに対してライブラリやコマンドラインインターフェースも書ける。すべて、上で説明したような似たコードを使ってね。それって結構すごいことだよ。非SPAの場合は、純粋なHTMLを使って「返された表現のフィールドを参照している」と考えなくてもいいけど、ユーザーとユーザーエージェントはそれをやってるんだ。

ここでの細かいことには同情するけど、Fieldingの論文は面白かった。でも、これは負け戦だよ。「REST API」を見ると、以下のことが安全に想定できる: - APIはJSONを返す - CRUDアクションはPOST/GET/PUT/DELETEにマッピングされている - チームは正しいステータスコードについて常に議論していて、少なくともいくつかはHTTP仕様に反して使われている - リストエンドポイントが複雑なフィルターをサポートするためにPOSTに変更された可能性が高い こういうのは、アジャイルやCI、DevOpsと同じで、元の定義にこだわるか、意味の拡散に従って一般的に理解されている用語を使うかのどちらかだね。

チームは正しいステータスコードについていつも議論してて、少なくともいくつかはHTTP仕様に反して使われてる。 ここでクスッときた。ほんとその通り!

そうだね。個人的には、みんなもう少し自分たちを超えて、君が言ってることが「REST API」の本当の、正しい、現代的な意味だってことに同意すべきだと思う。

Hacker Newsで議論の続きを見る