39

この質問は、最適な REST API 設計と、ネストされたリソースとルート レベル コレクションのどちらを選択するかという問題に直面しています。

概念を説明するために、コレクションCityBusiness、およびがあるとしEmployeesます。典型的な API は、次のように構築できます。ABC、X7N、および WWW がキー、たとえば GUID であると想像してください。

GET Api/City/ABC/Businesses                       (returns all Businesses in City ABC)
GET Api/City/ABC/Businesses/X7N                   (returns business X7N)
GET Api/City/ABC/Businesses/X7N/Employees         (returns all employees at business X7N)
PUT Api/City/ABC/Businesses/X7N/Employees/WWW     (updates employee WWW)

これは、元のドメイン構造 (ビジネスは都市にあり、従業員はビジネスにある) に従っているため、クリーンに見えます。個々のアイテムは、コレクションの下のキーを介してアクセスできます (たとえば../Businesses、すべてのビジネスを../Businesses/X7N返し、個々のビジネスを返します)。

API コンシューマーができる必要があることは次のとおりです。

  • 都市でビジネスを獲得する(GET Api/City/ABC/Businesses)
  • ビジネスのすべての従業員を取得する(GET Api/City/ABC/Businesses/X7N/Employees)
  • 社員個人情報の更新(PUT Api/City/ABC/Businesses/X7N/Employees/WWW)

その 2 番目と 3 番目の呼び出しは、適切な場所にあるように見えますが、実際には不要な多くのパラメーターを使用しています。

  • ビジネスの従業員を取得するために必要なパラメーターは、ビジネスのキー ( X7N) だけです。
  • 個々の従業員を更新するために必要なパラメーターは、従業員のキー ( WWW)だけでした。

バックエンド コードには、ビジネスを検索したり、従業員を更新したりするための重要でない情報は必要ありません。したがって、代わりに、次のエンドポイントがより適切に表示されます。

GET Api/City/ABC/Businesses                       (returns all Businesses in City ABC)
GET Api/Businesses/X7N                            (returns business X7N)
GET Api/Businesses/X7N/Employees                  (returns all employees at business X7N)
PUT Api/Employees/WWW                             (updates employee WWW)

ご覧のとおり、ビジネスと従業員の新しいルートを作成しましたが、ドメインの観点から見ると、それらはサブ/サブサブコレクションです。

どちらのソリューションも私にはあまりきれいに見えません。

  • 最初の例は不必要な情報を求めていますが、消費者にとって「自然」に見えるように構成されています (コレクションの個々のアイテムは下位のリーフを介して取得されます)。
  • 2 番目の例は必要な情報のみを要求しますが、「自然な」方法で構造化されていません。サブコレクションはルート経由でアクセスできます。
  • 従業員を追加するビジネスを知る必要があるため、新しい従業員を追加するときに個々の従業員ルートは機能しませんPOST Api/Businesses/X7N7/Employees。 .

私が考えていない、よりクリーンな第 3 の方法はありますか?

4

5 に答える 5

16

REST を特定の URI 命名規則の適用と混同しないでください。

リソースの命名方法は完全に二次的なものです。HTTP リソースの命名規則を使用しようとしています - これは REST とは関係ありません。ロイ・フィールディング自身は、上記で他の人が引用した文書の中で繰り返し述べています。REST はプロトコルではなく、アーキテクチャ スタイルです。

実際、Roy Fielding は 2008 年のブログ コメント ( http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven 6/20/2012) で次のように述べています。

「REST API は、固定のリソース名または階層 (クライアントとサーバーの明らかな結合) を定義してはなりません。サーバーは、独自の名前空間を制御する自由を持たなければなりません。代わりに、サーバーが適切な URI を構築する方法をクライアントに指示できるようにします。メディア タイプとリンク関係内でこれらの指示を定義することにより、HTML フォームと URI テンプレートで行われます。」

つまり、本質的に:

あなたが説明する問題は、実際には REST の問題ではありません。概念的には、HIERARCHY STRUCTURES と RELATIONAL STRUCTURES の問題です。

ビジネスは都市の「中に」あるため、都市の「ヒエラルキー」の一部と見なすことができますが、75 の都市にオフィスを持つ国際企業はどうでしょうか。次に、都市は突然、構造の上位レベルにビジネス名を持つ階層の下位要素になります。

ポイントは、データをさまざまな角度から見ることができ、見方によっては、階層として見るのが最も簡単かもしれないということです。ただし、同じデータを異なるレベルの階層として見ることができます。HTTP タイプのリソース名を使用している場合、HTTP によって定義された階層構造を入力したことになります。これは制約ですが、REST 制約ではなく、HTTP 制約です。

その角度から、シナリオにより適したソリューションを選択できます。顧客が会社名を提供するときに都市名を提供できない場合 (彼は知らない可能性があります)、都市名のみのキーを用意することをお勧めします。私が言ったように、それはあなた次第です.RESTはあなたの邪魔にはなりません...

さらに要点:

GET PUT などで HTTP を使用することを既に決定している場合、唯一の実際の REST 制約は次のとおりです。

    1. クライアントとサーバー間の事前の (「帯域外」) 知識を仮定してはなりません。*

その観点から、上記の提案 1 を見てください。システムに含まれる都市のキーを顧客が知っていると思いますか? 間違っています - それは落ち着きがありません。したがって、サーバーは何らかの方法で都市のリストを選択肢のリストとして提供する必要があります。では、ここに世界のすべての都市をリストするつもりですか? そうではないと思いますが、これをどのように計画しているかについていくつかの作業を行う必要があります。

    1. REST API は、リソースを表し、アプリケーションの状態を駆動するために使用されるメディア タイプを定義するために、その記述作業のほとんどすべてを費やす必要があります ...

上記の Roy Fielding ブログを読むと、かなり役立つと思います。

于 2013-10-17T15:46:12.437 に答える
3

3 つ目の方法は、Businesses と Employees のルート リソースを作成し、クエリ パラメーターを使用してコレクションをフィルター処理することです。

GET Api/Businesses?city=ABC                       (returns all Businesses in City ABC)
GET Api/Businesses/X7N                            (returns business X7N)
GET Api/Employees?businesses=X7N                  (returns all employees at business X7N)
PUT Api/Employees/WWW                             (updates employee WWW)

両方のソリューションは、サブリソースが親リソースに含まれている必要がある REST サブリソースの概念を使用します。

GET Api/City/ABC/Businesses

応答では、次によって提供されるデータも返す必要があります。

  GET Api/City/ABC/Businesses/X7N                 
  GET Api/City/ABC/Businesses/X7N/Employees 

同様に:

GET Api/Businesses/X7N

以下によって提供されるデータを返す必要があります。

GET Api/Businesses/X7N/Employees

応答のサイズが巨大になり、生成に必要な時間が増加します。

REST API をクリーンにするために、各リソースには、次のパターンに該当するバインドされた URI を 1 つだけ含める必要があります。

 GET  /resources
 GET  /resources/{id}
 POST /resources
 PUT  /resources/{id}

リソース間のリンクを作成する必要がある場合は、HATEOASを使用します

于 2013-10-14T05:29:53.333 に答える