REST APIの設計-異なるパラメーターを使用して同じURLパターンでRESTを介してリソースを取得する


92

REST urlの設計に関連する質問があります。ここでいくつかの関連する投稿を見つけました:同じリソースのさまざまなRESTful表現とここ:さまざまなフィールドによるGETリソースへのRESTful urlですが、ベストプラクティスとその理由についての応答は完全には明確ではありません。ここに例があります。

「ユーザー」リソースを表すためのREST URLがあります。IDまたはメールアドレスを使用してユーザーを取得できますが、URL表現はどちらも同じままです。多くのブログや本を読んでいると、人々はさまざまな方法でこれを行っていることがわかります。例えば

本やstackoverflowのどこかでこの実践を読んでください(私は再びリンクを見つけることができないようです)

GET /users/id={id}
GET /users/email={email}

多くのブログでこのプラクティスを読んでください

GET /users/{id}
GET /users/email/{email}

クエリパラメータは通常、URLで表されるリソースの結果をフィルタリングするために使用されますが、この方法も使用されているのを見てきました

GET /users?id={id}
GET /users?email={email}

私の質問は、これらすべてのプラクティスの中で、APIを使用する開発者にとって最も理にかなうものとその理由は何ですか?REST urlの設計と命名規則に関しては、明確なルールはないと思いますが、開発者がAPIをよりよく理解できるようにするためにどのルートを取るべきかを知りたかっただけです。

すべての助けに感謝します!


1
私はこれが少し古いことを知っていますが、同様のリソースを探しています。私はこの質問とあなたが探していたものにつまずきました。これは1つのスタックオーバーフロー
Joel Berger

回答:


102

私の経験でGET /users/{id} GET /users/email/{email}は、が最も一般的なアプローチです。また、提供されたidまたはでユーザーが存在しない場合、メソッドが404 Not Foundを返すことも期待しますemail。私が見ても驚かないでしょうGET /users/id/{id}(私の意見では、それは冗長です)。

他のアプローチに関するコメント

  1. GET /users/id={id} GET /users/email={email}
    • 私はこれを見たことはないと思います。もし見たとしたら、非常に混乱します。これは、パスパラメータを使用してクエリパラメータを模倣しようとしているようなものです。
  2. GET /users?id={id} GET /users?email={email}
    • フィルター処理にクエリパラメーターを使用することについて言及したとき、頭に釘を打ったと思います。
    • このリソースをan と(eg )の両方で呼び出すことは理にかなっていますか?そうでない場合は、このような単一のリソースメソッドを使用しません。idemailGET /users?id={id}&email={email}
    • フィルタリング用のオプションのクエリパラメータを使用してユーザーのリストを取得するためのこのメソッドを期待しますが、パラメータの中にidemailまたは一意の識別子が含まれることを期待しません。たとえばGET /users?status=BANNED、禁止されたユーザーのリストを返す場合があります。

関連する質問からこの回答を確認してください。


ご入力ありがとうございます。実際にあなたは正しいです。「RESTful java with Jax-rs」の本で#1を読んだようですが、多少前後しています。しかし、私はそれをstackoverflow自体の質問の1つに対する回答として読んだことを非常にはっきりと覚えています(同僚に証明するためにそのリンクを見つけるために非常に懸命に努力していると私が信じる:))と#2はまさに私がいたものです探している。設計に関するいくつかのフィードバック。ありがとうございました!
shahshi15 2013

PS:これがここのルールに違反するものかどうかはわかりませんが、他の質問にも少し光を当てることができますか?お願いします?:) stackoverflow.com/questions/20508008/...
shahshi15

の冗長ステートメントについて明確にするために/users/id/{id}、これは拡張機能を可能にし、いくつかの識別子(id、guid、name)を介して1つのリソースにアクセスできるようにします。こちら
Daniel Dubovski

4
私の答えは、たとえば特定のユーザーを参照する適切な方法は、/ users / {id}になるということです。ユーザーの一意の識別子ではない特定のメールアドレスでユーザーを検索したい場合は、/ users?email = {email}を使用します。これは、ユーザーのコレクションをフィルタリングする方法であり、特定のリソースをそのリソースで識別するのではないためです/ users / {id}と同じ識別子。
Kevin M

正解です。それのためのサムサップ。:あなたのリソースマッピングが何かのようにする必要がありますので、RESTは、名前中心であるべきと私はやって推薦する唯一のことは、あなたのAPIビットを変更することもあるGET /user/1234し、ないGET /users/123
サミー

36

これを実用的に見ると、ユーザーのコレクションがあります。

/users   # this returns many

各ユーザーには専用のリソースロケーションがあります。

/users/{id}    # this returns one

ユーザーを検索する方法もいくつかあります。

/users?email={email}
/users?name=*bob*

これらはすべて/ usersへのクエリパラメータであるため、1のリストであっても、すべてリストを返す必要があります。

私はここで、特にこれについて説明する実用的なRESTful API設計に関するブログ投稿をここに書きました:http : //www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


返信vinayをありがとう。しかし、これを別の視点で考えると、{email}は常に{id}と同じように常に1つの結果を返します。本当に検索しているのなら、メールと同じように?id = {id}を使用してみませんか?とにかく整合性があるのか​​と思っていました。PS:Stackoverflowの新機能です。答えは1つだけです。しかし、返信ありがとうございます!感謝します。たぶん、あなたは同様に、この1で私を助けることができる:stackoverflow.com/questions/20508008/...
shahshi15

7
これは、APIデザインの「デザイン」の側面が関係する場所です。リソースには専用の場所が必要です。場所はどこですか?場所はIDですか?もしそうなら、IDで「検索」するのではなく、IDで「取得」します。しかし、他のすべてで検索します。もちろん、ここに明確な規則はありません。それは単なる展望です:)
Vinay Sahni

6
また、この方法でAPIがより安定することを主張します。あなたはあなたのIDが一意であることを本当に知っていますが、あなたは本当にメールアドレスについて本当に確信していますか?一意であっても、ユーザーが変更できるため、おそらく永続的ではありません。したがって、/ users?email = {email}は、これが実際にクエリであり、永続的な識別子を持つリソースへのアクセスではないことを明確にします。
lex82、2015

これは実際にはもっと正しい答えだと思います。電子メールアドレスでコレクションをフィルタリングすると、ワイルドカードベースになる可能性があるため、常に1つの結果しか返されない場合があります。
Kevin M

@VinaySahni次のようなパターンについてどう思いますか:/user?by=email&email="abc@pqr.com "/ user?by = id&id =" xashkhx "/ users?filterA =" a "&filterB =" b "(複数複数のユーザー向け)
Shasak

2

ユーザーリソースについて

パス/usersでは、常にユーザーリソースのコレクションが返されます。

パス上では、/users/[user_id]いくつかのことが起こることが期待できます。

  1. 識別子[user_id]を持つユーザーリソースを表すシングルトンリソースを取得する必要があります。
  2. ID [user_id]のユーザーが存在しない場合、見つからない404応答、または
  3. リクエストされたユーザーリソースへのアクセスが許可されていない場合は、禁止された401

各シングルトンはパスと識別子によって一意に識別され、これらを使用してリソースを検索します。シングルトンに複数のパスを使用することはできません。

/usersクエリパラメーター(GETパラメーター)を使用してパスをクエリできます。これにより、要求された条件を満たすユーザーのコレクションが返されます。返されるコレクションには、ユーザーリソースが含まれている必要があり、すべてレスポンスで識別リソースパスが含まれています。

パラメータは、コレクションのリソースに存在する任意のフィールドです。firstNamelastNameid

メールについて

電子メールは、リソースまたはユーザーリソースのプロパティ/フィールドのいずれかです。

-ユーザーのプロパティとしてのメール:

フィールドがユーザーのプロパティである場合、ユーザーの応答は次のようになります。

{ 
  id: 1,
  firstName: 'John'
  lastName: 'Doe'
  email: 'john.doe@example.com'
  ...
}

つまり、メールに特別なエンドポイントはありませんが、次のリクエストを送信することにより、メールでユーザーを見つけることができます /users?email=john.doe@example.com。電子メールがユーザーに固有であると仮定すると、電子メールに一致するユーザーアイテムが1つあるコレクションが返されます。

-リソースとしてのメール:

ただし、ユーザーからのメールもリソースである場合。次に/users/[user_id]/emails、IDを持つユーザーのメールアドレスのコレクションを返すAPIを作成できますuser_id/users/[user_id]/emails/[email_id]user_idと['email_id']を持つユーザーのメールを返します。識別子として何を使用するかはあなた次第ですが、私は整数に固執します。削除するメールDELETEを識別するパスにリクエストを送信して、ユーザーからメールを削除できます。したがって、たとえばDELETEon /users/[user_id]/emails/[email_id]は、user_idを持つユーザーが所有するemail_idを持つメールを削除します。ほとんどの場合、そのユーザーのみがこの削除操作を実行できます。他のユーザーは401応答を受け取ります。

ユーザーが1つのメールアドレスしか持てない場合は、/users/[user_id]/email これに固執することができます。これにより、シングルトンリソースが返されます。ユーザーはPUT、そのURLにあるメールアドレスを入力することにより、自分のメールアドレスを更新できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.