RESTful APIでパスパラメータとクエリパラメータを使用するのはいつですか?


141

RESTful APIを非常に予測可能にしたいと考えています。クエリパラメータを使用するのではなく、URIを使用してデータのセグメンテーションを行うタイミングを決定するためのベストプラクティスは何ですか。

ページネーション、並べ替え、およびグループ化をサポートするシステムパラメータは、「?」の後に来るのが理にかなっています。しかし、 'status'や 'region'などのフィールド、またはコレクションをセグメント化するその他の属性についてはどうでしょうか。それらもクエリパラメータになる場合、パスパラメータをいつ使用するかを知る上での経験則は何ですか?


1
同様の質問がここに回答されています... stackoverflow.com/questions/3198492/...
ラリットMehra

回答:


239

RESTful API設計のベストプラクティスは、パスパラメータを使用して特定の1つまたは複数のリソースを識別し、クエリパラメータを使用してそれらのリソースをソート/フィルタリングすることです。

ここに例があります。CarというエンティティにRESTful APIエンドポイントを実装するとします。エンドポイントは次のように構成します。

GET /cars
GET /cars/:id
POST /cars
PUT /cars/:id
DELETE/cars/:id

この方法では、フェッチするリソースを指定するときにのみパスパラメータを使用しますが、これはリソースのソートやフィルタリングを一切行いません。

次に、GETリクエストに車を色でフィルタリングする機能を追加したいとします。色はリソースではない(リソースのプロパティである)ため、これを行うクエリパラメーターを追加できます。このクエリパラメータを次のようにGET/carsリクエストに追加します。

取得する /cars?color=blue

このエンドポイントは、青い車だけが返されるように実装されます。

構文に関する限り、URL名はすべて小文字にする必要があります。エンティティ名が英語で通常2語の場合、キャメルケースではなくハイフンを使用して単語を区切ります。

/two-words


3
答えてくれてありがとうマイク。これは明確で単純な方法論です。私からの賛成票に値する。それでも、多くの場合、開発者は「車/青」のアプローチを選択します。そうする理由は何なのかと思います...おそらく、必須のフィールドにパスパラメータを作成することを決定するか、それを示すためにそれを行うかもしれませんデータベースはその断片によって分割されます。
cosbor11 2015

1
彼らの推論が何であるか私にはわかりません。正直なところ、私はそれに同意しません。慣例に従い、それをシンプルに保つことが最も理にかなっていると思います。そうすることで、APIのコンシューマーがAPIの機能にアクセスするために何をする必要があるかを正確に理解できるようになります。
マイク

3
cars / 1 /?color = blueの代わりに/ cars?id = 1&color = blueはどうでしょうか。基本的に、各シナリオで車のリソースをフィルタリングしています
mko

1
ID 1の車は1つしか存在しないので間違っていますが、青の車は多分多いでしょう。アイデンティティとフィルタには違いがあります
ポール、

1
パスパラメータの使用が非常に普及している理由に関する私の仮説は、RESTの原則を十分に理解していない人々(特にRuby on Rails)によって設計されたフレームワークから多くの開発者が学んだためです
Chris Broski

58

この主題について考える基本的な方法は次のとおりです。

URIは、リソースTYPEの特定のインスタンスを一意に識別するリソース識別子です。人生の他のすべてと同様に、すべてのオブジェクト(あるタイプのインスタンス)には、時間不変または時間的である属性のセットがあります。

上記の例では、自動車は非常に具体的なオブジェクトであり、メーカー、モデル、VINなどの属性があり、変化することはありません。色、サスペンションなどは、時間とともに変化する可能性があります。したがって、時間の経過とともに変化する可能性のある(時間的な)属性を使用してURIをエンコードすると、同じオブジェクトに対して複数のURIが生成される可能性があります。

GET /cars/honda/civic/coupe/{vin}/{color=red}

そして数年後、この同じ車の色が黒に変更された場合:

GET /cars/honda/civic/coupe/{vin}/{color=black}

車のインスタンス自体(オブジェクト)は変更されていません。変更されたのは色だけです。同じオブジェクトインスタンスを指す複数のURIがあると、複数のURIハンドラーを作成する必要があります。これは効率的な設計ではなく、もちろん直感的ではありません。

したがって、URIは決して変更されず、存続期間を通じてそのリソースを一意に識別し続ける部分のみで構成する必要があります。変更される可能性があるものはすべて、クエリパラメータ用に予約する必要があります。

GET /cars/honda/civic/coupe/{vin}?color={black}

結論-ポリモーフィズムを考えてください。


2
興味深いパラダイム..これは、一般的に使用されるデザインパターンですか?ドキュメントでこれを使用するいくつかのAPIまたはこの戦略を概説するいくつかのリファレンスを提供できますか?
cosbor11 2017年

1
「URIは、リソースTYPEの特定のインスタンスを一意に識別するリソース識別子です」と書いたときに、「タイプ」をどのように強調したかが気に入っています。それは重要な違いだと思います。
jrahhali 2017年

15

REST APIでは、予測可能なURIを過度に気にする必要はありません。URIの予測可能性の提案そのものが、RESTfulアーキテクチャーの誤解を暗示しています。これは、クライアントが実際にURIを作成する必要があることを前提としています。

ただし、本当のREST APIではなく、「RESTにインスパイアされた」API(Googleドライブのものなど)を作成していると思います。これらの場合、経験則は「パスパラメータ=リソースの識別」と「クエリパラメータ=リソースのソート」です。したがって、問題は、ステータス/リージョンなしでリソースを一意に識別できるかということです。はいの場合、おそらくそのクエリパラメータです。いいえの場合、そのパスパラメータ。

HTH。


11
良いAPIは予測可能であるべきだと思います。RESTfulまたはその他。
cosbor11

3
私はそう思う。エンドポイントに任意の名前を付けるのではなく、URIがどのように形成されるかについて、韻と理由が必要です。常にドキュメントを参照せずにAPIクライアントを直感的に作成できる場合、私の意見では良いAPIを作成したことになります。
cosbor11、2015

2
「常にドキュメントを参照せずにAPIクライアントを直感的に作成できる場合」。ここで、RESTに対する理解が異なると思います。APIクライアントがURLを「構築」する必要はありません。前のAPI呼び出しの応答から選択する必要があります。あなたが類推としてウェブサイトをとるなら...あなたはfacebook.comに行き、次にイベントページへのリンクを選択します。入力するのをやめたので、facebookイベントURLが「予測可能」であるかどうかは気にしません。ハイパーメディアリンクからアクセスできます。REST APIについても同様です。したがって、URIはあなた(サーバー)にとって意味がありますが、クライアントにとっては意味がありません
Oliver McPhee

2
メモを追加しました。これは、URIが理解しやすいパターンに従っていないことを意味するのではなく、RESTful APIの制約ではないことを意味します。この領域の最大の問題は、クライアントが自分でURLを作成する必要があると想定している人々です。存在してはならないクライアントとサーバー間の結合を作成するので、それらはすべきではありません。(例-サーバーは、すべてのクライアントアプリケーションを中断せずにURLを変更できません)。REST APIでは、サーバーはそれらを自由に変更できます。
オリバーマクフィー

3
次の単語を使用するための+1:「 'path params = resource Identification' and 'query params = resource sorting'」。これは本当に私にとってそれを片付けました。
Doug

3

かつて、主なリソースであるAPIを設計しましたpeople。通常、ユーザーはフィルターを要求するpeopleため、ユーザーが/people?settlement=urban毎回何かを呼び出すのを防ぐために、/people/urban後で簡単に追加できるように実装しました/people/rural。また、これにより、/people後で役立つすべてのリストにアクセスできます。要するに、私の推論は一般的なサブセットへのパスを追加することでした

ここから:

一般的なクエリのエイリアス

平均的な消費者にとってAPIエクスペリエンスをより快適にするために、条件のセットを簡単にアクセスできるRESTfulパスにパッケージ化することを検討してください。たとえば、上記の最近閉じたチケットのクエリは、次のようにパッケージ化できます。GET /tickets/recently_closed


1

一般的に言って、リソースに明らかな「階層」がある場合は、次のようにパスパラメータを使用する傾向があります。

/region/state/42

その単一のリソースにステータスがある場合、次のことができます。

/region/state/42/status

ただし、「リージョン」が実際に公開されているリソースの一部ではない場合は、おそらく、ページングと同様に、クエリパラメーターの1つとして属しています(前述のとおり)。


0

セグメンテーションはより階層的で「かなり」ですが、制限される場合があります。

たとえば、3つのセグメントを持つURLがある場合、それぞれが異なるパラメーターを渡して、メーカー、モデル、色で車を検索します。

www.example.com/search/honda/civic/blue

これは非常にきれいなURLであり、エンドユーザーが覚えやすいものですが、今ではこの構造に固執しています。検索でユーザーがすべての青い車、またはすべてのホンダシビックを検索できるようにしたいとしますか?クエリパラメータは、キーと値のペアを提供するため、これを解決します。だからあなたは渡すことができます:

www.example.com/search?color=blue
www.example.com/search?make=civic

これで、キーを使用して値を参照する方法ができました-クエリコードで「color」または「make」。

より多くのセグメントを使用して、次のような種類のキー値構造を作成することで、これを回避できます。

www.example.com/search/make/honda/model/civic/color/blue

それが理にかなっていると思います


-2

URLの例: /rest/{keyword}

このURLはパスパラメータの例です。このURLデータはを使用して取得できます@PathParam

URLの例: /rest?keyword=java&limit=10

このURLはクエリパラメータの例です。このURLデータはを使用して取得できます@Queryparam

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