REST APIは複数のリソースを単一の複合リソースとして返すことができますか?


9

REST APIの作成を進めており、現在、次の問題が発生しています。

  • Foo最初のリソースです。CRUD操作は/foo/URI を介して適用できます。
  • Bar2番目のリソースです。CRUD操作は/bar/URI を介して適用できます。
  • Every Fooは0または1に関連付けられていますBar。のBarサブリソースとして扱わないのFooBar、複数Fooのs 間で同じインスタンスを共有できるためです。ですから、の代わりに独立したURI経由でアクセスする方がよいと考えました/foo/[id]/bar

私の問題は、かなりの場合、インスタンスを要求するクライアントがFoo関連するインスタンスにも関心があることBarです。現在、これは、1つではなく2つのクエリを実行する必要があることを意味します。1つのクエリで両方のオブジェクトを取得できる方法を紹介したいのですが、そのためのAPIをモデル化する方法がわかりません。これまでに思いついたこと:

  • 次のようなクエリパラメータを導入できます/foo/[id]?include_bar=true。このアプローチの問題は、応答のリソース表現(JSON構造など)が異なるように見える必要がある(たとえば、{ foo: ..., bar: ... }単にシリアライズされたものではなく、コンテナーなどFoo)ため、Fooリソースエンドポイントが「異種」になることです。それは良いことではないと思います。をクエリする場合/foo、クライアントはクエリパラメータに関係なく、常に同じリソース表現(構造)を取得する必要があります。
  • もう1つのアイデアは、新しい読み取り専用エンドポイントを導入すること/fooandbar/[foo-id]です。この場合、のような表現を返すことは問題ありません。これ{ foo: ..., bar: ... }は、fooandbarリソースの「公式」表現にすぎないためです。ただし、そのようなヘルパーエンドポイントが本当にRESTfulであるかどうかはわかりません(これが質問のタイトルに「can」と書いた理由です。もちろん、技術的には可能ですが、それが良いアイデアかどうかはわかりません)。

どう思いますか?他の可能性はありますか?


フーとバーの関係の用語は何ですか?BarはFooの親だと言えますか?
Nathan Merrill

Bar、に関連付けられていないと存在できませんFoo。ただし、上で書いたように、複数Fooのが同じを共有する可能性がありますBar。アソシエートFooなしでを作成できるはずなBarのでBar、親として扱われるべきではないと思います。
ceran 2016年

1
私は、ドメインモデルの関係を直接URIに変換し、リソースドメインエンティティと同等にすることによって、私が経験したいくつかの問題を経験していると思います。それは興味ありますREST APIはハイパーテキスト主導型でなければなりません。4番目のポイントへの特別な注意
Laiv

回答:


5

レベル3のREST APIはあなたを返しますFooし、また、関連を示すリンクBar

GET /foo/123
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456"/>
</foo>

次に、リンクのナビゲーションを可能にする「ドリルダウン」機能をAPIに追加できます。

GET /foo/123?drilldown=bar
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456">
    <bar id="456">
      ..bar stuff...
    </bar>
  </link>
</foo>

ドリルダウン機能は、APIの前に座って応答をインターセプトします。それはドリルダウン呼び出しを行い、応答を呼び出し元に戻す前に詳細を入力します。

これはレベル3 RESTでかなり一般的なことです。遅いhttpでのクライアント/サーバーのチャットを大幅に減らすからです。私が働いている会社は、まさにこの機能を備えたレベル3のREST APIを作成しています。

更新: その価値については、JSONでは次のようになります。これは、APIが構造化する方法です。ドリルダウンをネストして、リンクのリンクなどをプルできることに注意してください。

GET /foo/123?drilldown=bar

{
  "self": {
    "type": "thing.foo",
    "uri": "/foo/123=?drilldown=bar",
    "href": "http://localhost/api/foo/123?drilldown=bar"
  },
  "links": [
    {
      "rel": "bar",
      "rev": "foo",
      "type": "thing.bar",
      "uri": "/bar/456",
      "href": "http://localhost/api/bar/456"
    }
  ],
  "_bar": [
    {
      "self": {
        "type": "thing.bar",
        "uri": "/bar/456",
        "href": "http://localhost/api/bar/456"
      },
      "links": [
        {
          ..other link..
        },
        {
          ..other link..
        }
      ]
    }
  ]
}

興味深いことに、私はすでにハイパーメディアリンク/コントロールを使用してURIへの密結合を削除していますが、非常に有望であると思われる「ドリルダウン」のアイデアについては考えていません。JSON表現はどのように見えますか?現時点では、リソースの各JSON表現にはlinks配列が含まれており、各エントリはreluriフィールドを持つリンクオブジェクトです(xmlの例と同様)。各リンクオブジェクト(たとえばdata)に3番目のフィールドを追加する必要がありますか?基準はありますか?
ceran 2016年

ドリルダウンは実際には残りの機能ではないため、標準はありません(少なくとも私は知っています)。
Qwerky

私たちのアプリケーションで使用しているstateless.co/hal_specification.htmlなど、いくつかの標準が提案されています。それはあなたの例にとても近いです。
ピートカーカム2016

4

すべてのクエリの95%がFooだけでなくもBarFoo必要な場合は、をリクエストしたときに、それオブジェクト返すだけですFoo。プロパティbar(またはリレーションシップの他の用語)を追加し、Barそこにオブジェクトを配置するだけです。関係が存在しない場合は、nullを使用します。

私はあなたがこれを考えすぎていると思います:)


その数(95%)を思い付くべきではなかった、それは間違いでした、すみません。私が言いたかったのは、リクエストの大部分が同時に両方のリソースに関心があるということです。ただし、にのみ関連する関連する数のリクエストがまだあります。各リクエストはメモリ内で非常に巨大なFooのでBar(のサイズの約3倍から4倍Foo)、Barクライアントが明示的にリクエストしない限り、を返したくありません。
ceran 2016年

私たちはどれくらい大きいですか?私はそれを作るために起こっていることを疑うその転送時間の違いの多くを、私はスピードの上にきれいなAPIを好む
ネイサン・メリル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.