RESTful APIを非常に予測可能なものにしたい。クエリパラメータを使用するのではなく、URIを使用してデータのセグメンテーションを行うタイミングを決定するためのベストプラクティスは何ですか。
ページネーション、ソート、グループ化をサポートするシステムパラメータが「?」の後にあることは私にとって理にかなっていますしかし、「ステータス」や「地域」などのフィールドや、コレクションをセグメント化するその他の属性についてはどうでしょうか?それらがクエリパラメータでもある場合、パスパラメータをいつ使用するかを知る上での経験則は何ですか?
RESTful API設計のベストプラクティスは、特定の1つまたは複数のリソースを識別するためにパスパラメーターを使用し、それらのリソースを並べ替え/フィルターするためにクエリパラメーターを使用することです。
以下に例を示します。 CarというエンティティにRESTful APIエンドポイントを実装するとします。次のようにエンドポイントを構成します。
GET /cars
GET /cars/:id
POST /cars
PUT /cars/:id
DELETE /cars/:id
この方法では、取得するリソースを指定する場合にのみパスパラメーターを使用しますが、これはリソースの並べ替え/フィルター処理を一切行いません。
GETリクエストで色で車をフィルタリングする機能を追加したいとします。色はリソースではない(リソースのプロパティである)ため、これを行うクエリパラメーターを追加できます。このクエリパラメータをGET /cars
リクエストに追加するには、次のようにします。
GET /cars?color=blue
このエンドポイントは、青い車のみが返されるように実装されます。
構文に関する限り、URL名はすべて小文字にする必要があります。通常、英語で2単語のエンティティ名がある場合、キャメルケースではなく、ハイフンを使用して単語を区切ります。
例/two-words
この主題について考える基本的な方法は次のとおりです。
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}
結論-ポリモーフィズムを考えてください。
REST APIでは、予測可能なURIを過度に心配するべきではありません。 URIの予測可能性の提案は、RESTfulアーキテクチャの誤解を暗示しています。クライアントがURIを構築する必要があると想定していますが、実際にURIを構築する必要はありません。
ただし、真のREST APIを作成するのではなく、「RESTに触発された」API(Googleドライブなど)を作成するものと想定しています。これらの場合、経験則は「path params =リソースの識別」と「query params =リソースの並べ替え」です。質問は、ステータス/地域なしでリソースを一意に識別できますか?はいの場合、おそらくクエリパラメータです。いいえの場合、そのパスパラメータ。
HTH。
メインリソースがpeople
であるAPIを設計したら。通常、ユーザーはフィルター処理されたpeople
を要求するため、ユーザーが毎回/people?settlement=urban
のようなものを呼び出さないように、後で/people/urban
を簡単に追加できる/people/rural
を実装しました。また、後で使用する場合は、/people
リスト全体にアクセスできます。要するに、私の推論は、共通のサブセットにパスを追加することでした
ここ から:
一般的なクエリのエイリアス
APIエクスペリエンスを平均的な消費者にとってより快適にするために、一連の条件を簡単にアクセスできるRESTfulパスにパッケージ化することを検討してください。たとえば、上記の最近閉じたチケットクエリは、
GET /tickets/recently_closed
としてパッケージ化できます。
RLの例:/rest/{keyword}
このURLはパスパラメーターの例です。 @PathParam
を使用して、このURLデータを取得できます。
RLの例:/rest?keyword=Java&limit=10
このURLはクエリパラメータの例です。 @Queryparam
を使用して、このURLデータを取得できます。
セグメンテーションはより階層的で「きれい」ですが、制限される場合があります。
たとえば、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
理にかなっていることを願っています。
一般的に、次のようなリソースに明らかな「階層」がある場合、パスパラメーターを使用する傾向があります。
/region/state/42
その単一のリソースにステータスがある場合、次のことが可能です。
/region/state/42/status
ただし、 'region'が実際に公開されるリソースの一部ではない場合、おそらく(前述の)ページネーションと同様のクエリパラメーターの1つとして属します。