web-dev-qa-db-ja.com

REST APIベストプラクティス:パラメータをどこに置くか

REST AP​​Iには、少なくとも2つの方法でパラメータを指定できます。

  1. URLパスの一部として (つまり/api/resource/parametervalue
  2. クエリ引数として (すなわち/api/resource?parameter=value

ここでのベストプラクティスは何ですか? 1を使用する場合と2を使用する場合の一般的なガイドラインはありますか?

現実世界の例:Twitterは間隔を指定するためにクエリパラメータを使用します。 (http://api.Twitter.com/1/statuses/home_timeline.json?since_id=12345&max_id=54321

これらのパラメータをURLパスに入れる方が良い設計と考えられますか?

348

文書化されたベストプラクティスがある場合、私はまだそれらを見つけていません。ただし、URLのどこにパラメータを配置するかを決定するときに使用するいくつかのガイドラインがあります。

オプションのパラメータは、クエリ文字列に入れる方が簡単な傾向があります。

パラメータ値が既存のリソースに対応していないときに404エラーを返したい場合は、パスセグメントパラメータを使用します。例えば/customer/232ここで、232は有効な顧客IDではありません。

しかし、空のリストを返したい場合は、パラメータが見つからない場合はクエリ文字列パラメータを使用することをお勧めします。例えば/contacts?name=dave

パラメータがURI空間のサブツリー全体に影響を与える場合は、パスセグメントを使用してください。例えば言語パラメータ/en/document/foo.txt/document/foo.txt?language=en

クエリパラメータではなく、パスセグメントに一意の識別子を含めることをお勧めします。

URIの公式な規則はこのRFC仕様書にあります ここ 。 URIをパラメータ化するための規則を定義する、非常に有用な別のRFC仕様 here もあります。

254
Darrel Miller

回答が遅れていますが、共有されていること、つまりリクエストにはいくつかの種類の「パラメータ」があることについて、さらにいくつかの洞察を追加します。これを考慮する必要があります。

  1. ロケーター - 例IDやアクション/ビューなどのリソース識別子
  2. フィルタ - 例一連の結果を検索、ソート、または絞り込むためのパラメータ。
  3. 州 - 例セッションID、APIキー、whatev.
  4. コンテンツ - 例保存するデータ.

それでは、これらのパラメータを設定できるさまざまな場所を見てみましょう。

  1. ヘッダーとクッキーをリクエストする
  2. URLクエリ文字列( "GET" vars)
  3. URLパス
  4. ボディクエリ文字列/マルチパート( "POST"変数)

一般的には、状態情報の種類に応じて、Stateをヘッダーまたはcookieに設定します。私たち全員がこれに同意できると思います。必要に応じて、カスタムhttpヘッダー(X-My-Header)を使用してください。

同様に、Contentには、クエリ文字列として、またはhttp multipartおよび/またはJSONコンテンツとして、所属する場所が1つだけあります。これは、コンテンツを送信するときにサーバーから受け取るものと一致しています。それであなたは失礼ではなく、違うやり方でやるべきです。

"id = 5"、 "action = refresh"、 "page = 2"などのロケーターは、mysite.com/article/5/page=2のようにURLパスとして持つのが理にかなっています。 5は明らかにid 5)のarticle型のデータを取得することを意味し、追加のパラメータはURIの一部として指定されます。 URIの特定の時点の後に「フォルダー」がペアになったKey-Valueであることがわかっている場合は、それらはpage=2、またはpage/2の形式になります。

フィルタは常にクエリ文字列に含まれます。正しいデータを見つけるためのものではありますが、ロケータが返すもののサブセットまたは変更を返すためだけにあるからです。 mysite.com/article/?query=Obama(サブセット)内の検索はフィルターであり、/article/5?order=backwards(修正)も検索です。それが何を呼んでいるのかではなく、それが何をしているのか考えてみてください。

"view"が出力フォーマットを決定するならば、それはフィルタ(mysite.com/article/5?view=pdf)です。なぜならそれは我々が欲しいリソースに戻るのではなく見つけられたリソースの修正を返すからです。代わりに、記事のどの部分を表示するかを決定した場合(mysite.com/article/5/view=summary)、それはロケーターです。

一連のリソース - を絞り込むことを忘れないでください。リソース内で何か特定のものを見つけることは、見つけることです。サブセットフィルタリングは、結果をいくつでも返すことができます(0でも)。位置を特定することで、常に何かの特定のインスタンスが見つかるでしょう(存在する場合)。修正フィルタリングは、修正を除いてロケータと同じデータを返します(そのような修正が許可されている場合)。

彼らがものをどこに置くべきかについて迷ったならば、これが人々に若干のeurekaの瞬間を与えるのを助けたことを願っています!

152
Tor Valamo

デザイン次第です。 HTTP上のRESTでのURIに関する規則はありません(主なことはそれらがユニークであるということです)。それはしばしば味と直感の問題になります...

私は以下のアプローチを取ります:

  • url path-element:リソースとそのpath-elementはディレクトリトラバーサルとサブリソースを形成します(例:/ items/{id}、/ users/items)。よくわからないときは、あなたの同僚にそのトラバーサルと彼らが「別のディレクトリ」で考えていると思うかどうか尋ねてみると、おそらくパス要素が正しい選択です
  • urlパラメータ:実際にトラバースがない場合(複数のクエリパラメータを持つ検索リソースはそのための非常に良い例です)
21
manuel aldana

IMOでは、パラメータはクエリ引数として優れているはずです。 urlはリソースを識別するために使用され、追加されたクエリパラメータはリソースのどの部分を必要とするか、リソースが持つべき任意の状態などを指定するために使用されます。

18
PeterWong

RESTの実装に従って、

1) パス変数 連絡先や歌の例のように、リソースに対する直接のアクションに使用されます。
GET etc/api/resource/{songid}または
GET etc/api/resource/{contactid}はそれぞれのデータを返します。

2) クエリパーマ/引数 曲のメタデータのような間接リソースに使用されます。例えば、GET/api/resource/{songid}?metadata = genresそれはその特定の曲のジャンルデータを返します。 。

17
Satish Bellapu

"Pack"およびPOST universe-resource-locatorが提供する "context"に対してデータを検索します。これは、ロケーターのために#1を意味します。

#2で制限を気にしてください。私はPOSTよりも#1を好む。

注意:制限事項については、

POST POSTパラメータの内容に最大サイズはありますか?

GET - GETリクエストの長さに制限はありますか? および _GETのURLパラメータの最大サイズ

pSこれらの制限は、クライアント機能(ブラウザ)とサーバ(設定)に基づいています。

16
dgm

URI規格によれば パスは階層的なパラメータのためのものであり、クエリは非階層的なパラメータのためのものです。おお。それはあなたにとって階層的なものは非常に主観的になることがあります。

複数のURIが同じリソースに割り当てられている状況では、識別に必要なパラメータをパスに、パラメータ(表現を構築するのに必要な)をクエリに入れるのが好きです。 (私にとっては、このほうがルーティングが簡単です。)

例えば:

  • /users/123/users/123?fields="name, age"
  • /users/users?name="John"&age=30

Map reduceのために私は以下のアプローチを使うのが好きです。

  • /users?name="John"&age=30
  • /users/name:John/age:30

したがって、URIをどのように構成するかは、実際にはあなた(およびサーバー側のルーター)次第です。

注意:これらのパラメータはクエリパラメータです。ですから、あなたが本当にしているのは、単純な問い合わせ言語を定義することです。複雑なクエリ(andやor、thanなどの演算子を含む)では、既存のクエリ言語を使用することをお勧めします。 URIテンプレートの機能 は非常に限られています...

5
inf3rno

クライアント側でよくプログラマーとして、私はquery引数を好みます。また、私にとっては、URLパスをパラメータから分離し、明確さを増し、さらに拡張性を提供しています。それはまた私がURL/URI構築とパラメータビルダーとの間に別々の論理を持つことを可能にします。

ある種の木が関与している場合、私はマヌエル・アルダナが他の選択肢について言ったことが好きです。ユーザー固有の部分がこのように解決されているのがわかります。

4
Joe Plante

これが私の意見です。

クエリパラメータは、リクエストに対するメタデータとして使用されます。それらは、既存のリソース呼び出しに対するフィルタまたは修飾子として機能します。

例:

/calendar/2014-08-08/events

その日のカレンダーイベントを出すべきです。

特定のカテゴリのイベントが必要な場合

/calendar/2014-08-08/events?category=appointments

または30分以上のイベントが必要な場合

/calendar/2014-08-08/events?duration=30

Litmusテストは、リクエストがクエリパラメータなしでまだ処理できるかどうかをチェックすることです。

4
Jay

厳密で速いルールはありませんが、私が使用したいという純粋に概念的な観点からの経験則は、簡単にまとめると次のようになります。URIパス(定義による)はリソースを表し、クエリパラメータは基本的にそのリソースの修飾子です。 。これまでのところ、それはおそらく助けにはならないでしょう... REST AP​​Iでは、GETPUT、およびDELETEを使用して単一のリソースに作用する主な方法があります。したがって、パスで表現するのかパラメータとして表現するのかは、それらのメソッドが問題の表現にとって意味があるかどうかに減らすことができます。合理的にそのパスに何かPUTがあるでしょうか、そしてそうすることは意味的に正しいですか?もちろん、PUTをどこにでも置くことができ、それを処理するためにバックエンドを曲げることができますが、実際のリソースの表現に相当するものをPUTingする必要があります。コレクションの場合、POSTでも同じことができます。もしあなたが特定のコレクションに追加したいのであれば、それはPOSTに意味のあるURLでしょう。

いくつかのパスは親リソースの子にどのくらいの量を指すかを指す可能性があるので、これはまだいくつかの灰色の領域を残します。基本的なリソースがないため、これが描く1つの難しい線は、どのタイプの推移的表現もクエリパラメータを使用して実行する必要があることです。

元の質問(TwitterのAPI)で与えられた実世界の例に応じて、パラメーターは(階層ではなく)リソースの状態をフィルター処理する推移的な照会を表します。その特定の例では、これらの制約によって表されるコレクションに追加することは全く不合理であり、さらにそのクエリはオブジェクトグラフの観点からは意味をなさないパスとして表すことができないであろう。

このタイプのリソース指向パースペクティブを採用すると、ドメインモデルのオブジェクトグラフに簡単に直接マッピングでき、APIのロジックを明確になった時点ですべてが非常にきれいに動作し、かなり自己文書化された方法で動作するようになります。概念はまた、通常は不適切なデータモデル(すなわち、RDBMS)にマッピングされた従来のURLルーティングを使用するシステムから離れることによってより明確にすることができる。 Apache Sling は確かに始めるのに良い場所でしょう。 Zope のようなシステムにおけるオブジェクトトラバーサルディスパッチの概念もまた、より明確な類似物を提供します。

4
Matt Whipple

このトピックの1つの「ディメンション」は除外されていますが、非常に重要です。「ベストプラクティス」が、実装しているプラ​​ットフォーム、またはREST機能で強化されているプラ​​ットフォームで考慮する必要がある場合があります。

実用的な例:

今日の多くのWebアプリケーションはMVC(Model、View、Controller)アーキテクチャを実装しています。彼らは特定の標準的なパスが提供されていると仮定していますが、それらのWebアプリケーションに "Enable SEO URLs"オプションが付いている場合はなおさらです。

かなり有名なWebアプリケーション、つまりOpenCart eコマースショップについて言及してください。管理者が「SEO URL」を有効にすると、URLは次のような非常に標準的なMVC形式になると予想されます。

http://www.domain.tld/special-offers/list-all?limit=25

どこで

  • special-offersはURLを処理するMVCコントローラです(特別提供ページを表示)

  • list-allは、呼び出すコントローラのアクションまたは関数の名前です。 (*)

  • 1ページあたり25個の項目が表示されることを示す、limit = 25はオプションです。

(*)list-allは、わかりやすくするために使用した架空の関数名です。実際には、OpenCartおよびほとんどのMVCフレームワークには、暗黙の(そして通常URLでは省略されている)デフォルトのindex関数があります。これは、ユーザーがデフォルトのアクションを実行したいときに呼び出されます。したがって、実際のURLは次のようになります。

http://www.domain.tld/special-offers?limit=25

上記のような、今ではかなり標準的なアプリケーションまたはフレームワーク構造になっているため、URLを書き換えるWebサーバーが最適化されていることがよくあります(本当の「非SEO URL」はhttp://www.domain.tld/index.php?route=special-offers/list-all&limit=25になります)。

そのため、開発者として、あなたがシステム管理者でない限り、既存のインフラストラクチャに対処し、あなたの「ベストプラクティス」を適応させることに直面します。Apache/ NGinx書き換え設定を微調整する方法を正確に知ってください。に。

そのため、REST AP​​Iは、参照先のWebアプリケーションの標準に従うことで、一貫性と容易さ/速度の両方(したがって予算の節約)が得られるため、はるかに優れています。

上記の実用的な例に戻るには、一貫性のあるREST AP​​Iは次のようなURLを持つものになります。

http://www.domain.tld/api/special-offers-list?from=15&limit=25

または(SEO以外のURL)

http://www.domain.tld/index.php?route=api/special-offers-list?from=15&limit=25

"パス形成"引数と "クエリ形成"引数の組み合わせ。

2
Dario Fumagalli

私は一般的に#2に向いています、クエリ引数として(すなわち/ api/resource?parameter = value)。

3番目のオプションは、実際にparameter = valueを本体にポストすることです。

これは、それがマルチパラメータリソースに対してよりよく機能し、将来の使用に対してより拡張可能であるためです。

どちらを選んでも、必ず1つだけ選んで、組み合わせてはいけません。それは混乱を招くAPIにつながります。

2
NorthIsUp

パラメータをうまく処理できないREST AP​​Iがたくさんあります。よくある例の1つは、URIに個人を特定できる情報が含まれている場合です。

http://software.danielwatrous.com/design-principles-for-rest-apis/ /

当然の問題は、パラメータをまったくパラメータにすべきではなく、リクエストの _ header _ または _ body _ に移動する必要がある場合です。

1
Daniel Watrous

非常に興味深い質問です。

両方を使用することができます。この件に関して厳密な規則はありませんが、URIパス変数を使用することにはいくつかの利点があります。

  • キャッシュ :インターネット上のほとんどのWebキャッシュサービスは、クエリパラメータが含まれている場合、GETリクエストをキャッシュしません。これは、サーバー内のデータを変更するためにGET要求を使用するRPCシステムが多数あるためです(失敗します。Getは安全な方法でなければなりません)。

しかし、パス変数を使用すると、このサービスはすべてGET要求をキャッシュすることができます。

  • 階層 :パス変数は階層を表すことができます。/ City/Street/Place

それはデータの構造に関するより多くの情報をユーザに与えます。

ただし、データに階層関係がない場合でも、コンマまたはセミコロンを使用してPath変数を使用できます。

/市/経度、緯度

原則として、パラメータの順序が重要な場合はカンマを使用し、順序が重要でない場合はセミコロンを使用します。

/ IconGenerator /赤、青、緑

これらの理由とは別に、クエリ文字列変数を使用することが非常に一般的な場合がいくつかあります。

  • ブラウザがHTMLフォーム変数を自動的にURIに入れる必要があるとき
  • あなたがアルゴリズムを扱っているとき。たとえば、Googleエンジンはクエリ文字列を使用します。

http:// www.google.com/search?q=rest

まとめると、このメソッドの1つを使用する強力な理由はありませんが、できる限りURI変数を使用してください。

0
jfcorugedo