web-dev-qa-db-ja.com

REST APIベストプラクティス:パラメータ値のリストを入力として受け入れる方法

私たちは新しいREST AP​​Iを立ち上げようとしています、そして私たちは入力パラメータがどのようにフォーマットされるべきであるかについてのベストプラクティスについてのコミュニティ入力を欲しかった:

今のところ、私たちのAPIは非常にJSON中心です(JSONのみを返します)。 XMLを返すかどうかという議論は別の問題です。

私たちのAPI出力はJSON中心であるので、私たちの入力が少しJSON中心であるという道を歩んできました、そして私はそれが一般的に奇妙な、しかし奇妙な人にとって便利かもしれないと思っていました。

たとえば、複数の商品を一度に取得できる商品の詳細をいくつか取得するには、次のようにします。

http://our.api.com/Product?id=["101404","7267261"]

これを単純化する必要があります。

http://our.api.com/Product?id=101404,7267261

それともJSON入力が便利ですか。もっと痛みですか?

私たちは両方のスタイルを受け入れたいと思うかもしれませんが、その柔軟性は実際により多くの混乱と頭痛(メンテナンス容易性、ドキュメンテーションなど)を引き起こしますか?

もっと複雑なケースは、もっと複雑な入力を提供したい場合です。たとえば、検索で複数のフィルタを許可する場合は、次のようにします。

http://our.api.com/Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}

このようにリクエストの名前としてフィルタの種類(productTypeやcolorなど)を入力したくはありません。

http://our.api.com/Search?term=pumas&productType=["Clothing","Bags"]&color=["Black","Red"]

すべてのフィルタ入力をまとめてグループ化したいからです。

結局、これは本当に重要なのでしょうか。非常に多くのJSONユーティリティがあり、入力タイプはそれほど問題にならない可能性があります。

私たちのJavaScriptクライアントがAPIをAJAX呼び出しするのは、彼らの生活を楽にするためにJSON入力を認めるかもしれないことを知っています。

360
whatupwilly

一歩戻る

まず第一に、RESTはURIを普遍的にユニークなIDとして記述します。あまりにも多くの人々が、URIの構造や、どのURIが他よりも「安らか」なのかに気付いています。 この議論は、誰かに "Bob"という名前を付けることは "Joe"に名前を付けるよりも優れていると言うのと同じくらい面白いです - 両方の名前は "人を特定する"仕事を得ます。 URIは汎用的に一意なの名前にすぎません。

そのため、RESTの目では、?id=["101404","7267261"]?id=101404,7267261または\Product\101404,7267261よりも安らかであるかどうかについて議論することはやや無駄です。

さて、URIをどのように構築するかは、通常RESTfulサービスの他の問題に対する良い指標として役立つことができると言っています。あなたのURIにはいくつかの赤い旗があり、一般的に質問があります。

提案

  1. 同じリソースとContent-Locationに対する複数のURI

    私たちは両方のスタイルを受け入れたいと思うかもしれませんが、その柔軟性は実際により多くの混乱と頭痛(メンテナンス容易性、ドキュメンテーションなど)を引き起こしますか?

    URIはリソースを識別します。各リソースは、 one canonical URIを持つべきです。これは、2つのURIが同じリソースを指すことができないという意味ではありませんしかしそれを行うための明確に定義された方法があります。 JSONとリストベースのフォーマット(または他のフォーマット)の両方を使用することにした場合、どちらのフォーマットがメインの標準 URIであるかを決定する必要があります。同じ "リソース"を指す他のURIへのすべての応答は Content-Locationヘッダー を含むべきです。

    複数のURIを持つという名前のたとえに固執することは、人々にニックネームを持たせるのと同じです。それは完全に受け入れられ、しばしばかなり便利です、しかし私がニックネームを使っているなら私はまだ彼らのフルネームを知りたがっています - その人を指すための「公式の」方法。この方法で、誰かが彼らのフルネーム、 "Nichloas Telsa"で誰かに言及するとき、私は彼らが私が "ニック"と呼ぶのと同じ人について話しているのを知っています。

  2. あなたのURIで "検索"

    もっと複雑なケースは、もっと複雑な入力を提供したい場合です。たとえば、検索で複数のフィルタを許可したい場合は、.

    私の一般的な経験則は、あなたのURIが動詞を含んでいる場合、それは何かがおかしいことを示しているのかもしれません。 URIはリソースを識別しますが、そのリソースに対して行っているwhatを示すべきではありません。それがHTTPの仕事であり、言い換えれば、私たちの「ユニフォームインターフェース」です。

    URIで動詞を使用することは、名前の類似性を理解し難くするために、対話するときに名前を変更するのと同じです。私がボブと対話しているのであれば、こんにちは彼に言いたいのであれば、ボブの名前は "BobHi"にはなりません。同様に、商品を「検索」する場合、URI構造は「/ Product/...」から「/ Search/...」に変更しないでください。

最初の質問に答える

  1. ["101404","7267261"]101404,7267261について:私がここで提案するのは、単純にするためにJSON構文を避けることです(つまり、必要がないときはユーザーにURLエンコードを要求しないでください)。それはあなたのAPIをもう少し使いやすくするでしょう。さらに良いことに、他の人が推奨しているように、エンドユーザーにはおそらく最も馴染みのある標準的なapplication/x-www-form-urlencodedフォーマットを使いましょう(例:?id[]=101404&id[]=7267261)。それは「きれい」ではないかもしれませんが、きれいなURIは必ずしも使用可能なURIを意味するわけではありません。ただし、私の最初のポイントを繰り返しますが、最終的にはRESTについて話すときには、問題ではありません。あまりにも重く住まないでください。

  2. 複雑な検索URIの例は、製品の例とほぼ同じ方法で解決できます。 application/x-www-form-urlencodedフォーマットは、すでに多くの人が慣れ親しんでいる標準なので、もう一度使用することをお勧めします。また、2つをマージすることをお勧めします。

あなたのURI ...

/Search?term=pumas&filters={"productType":["Clothing","Bags"],"color":["Black","Red"]}    

URIエンコードされた後のあなたのURI ...

/Search?term=pumas&filters=%7B%22productType%22%3A%5B%22Clothing%22%2C%22Bags%22%5D%2C%22color%22%3A%5B%22Black%22%2C%22Red%22%5D%7D

に変換することができます...

/Product?term=pumas&productType[]=Clothing&productType[]=Bags&color[]=Black&color[]=Red

URLエンコードの要件を回避し、物事をもう少し標準的に見せることは別として、今ではAPIを少し均質化しています。ユーザーは、製品または製品リスト(両方ともRESTfulな用語で単一の「リソース」と見なされます)を取得する場合、/Product/... URIに関心があることを知っています。

308
nategood

値のリストをURLパラメータとして渡す標準的な方法は、それらを繰り返すことです。

http://our.api.com/Product?id=101404&id=7267261

ほとんどのサーバーコードはこれを値のリストとして解釈しますが、多くの場合は単一値の単純化がされているため、確認する必要があります。

区切られた値も大丈夫です。

あなたがサーバーにJSONを送る必要があるなら、私はそれをURLの中に見るのは好きではありません(それは異なるフォーマットです)。特に、URLにはサイズ制限があります(理論上ではないにしても実際には)。

RESTfulに複雑なクエリを実行する方法を2つ紹介します。

  1. クエリ要件をPOST、IDを受け取る(基本的に検索条件リソースを作成する)
  2. 上記のIDを参照して検索をGET
  3. 必要に応じてオプションでクエリ要件をDELETEしますが、それらの要件は再利用可能であることに注意してください。
201
Kathy Van Stone

最初:

2つの方法があると思います

http://our.api.com/Product/<id>:レコードが1つだけ欲しい場合

http://our.api.com/Product:全てのレコードが欲しいなら

http://our.api.com/Product/<id1>,<id2>:Jamesが示唆したように、Productタグの後に来るものはパラメータなのでオプションになることができます

それとも私が一番好きなのは:

RestFul WSのアプリケーション状態のエンジンとしてのハイパーメディア(HATEOAS)プロパティを使用して、http://our.api.com/Productと同等のURLを返すhttp://our.api.com/Product/<id>呼び出しを実行し、その後でそれらを呼び出すことができます。

2番目

あなたはURL呼び出しでクエリを行う必要があるとき。もう一度HATEOASを使うことをお勧めします。

1)http://our.api.com/term/pumas/productType/clothing/color/blackをget呼び出しします

2)http://our.api.com/term/pumas/productType/clothing,bags/color/black,redをget呼び出しします

3)(HATEOASを使用して) ` http://our.api.com/term/pumas/productType/ - >すべての服装可能なURLを受信します - >あなたが欲しいものを呼び出しますとバッグ) - >可能な色のURLを受け取る - >あなたが欲しいものを呼び出す

19
Diego Dias

RFC 6570 をチェックアウトすることをお勧めします。このURIテンプレートの仕様は、URLにパラメータを含める方法の多くの例を示しています。

7
Darrel Miller

最初のケース:

通常の商品検索は次のようになります。

http://our.api.com/product/1

だから私はベストプラクティスはあなたがこれを行うことになるだろうと考えて

http://our.api.com/Product/101404,7267261

セカンドケース

クエリ文字列のパラメータで検索 - これのように罰金。 []を使用する代わりに、ANDとORを組み合わせて使用​​したいと思います。

PSこれは主観的なことがあるので、あなたが快適に感じることをしなさい。

データをURLに入れる理由は、リンクをサイトに貼り付けることができるようにするか、ユーザー間で共有できるようにするためです。これが問題にならない場合は、必ずJSON/POSTを代わりに使用してください。

編集:熟考して考えると、このアプローチは複合キーを持つエンティティには適していますが、複数のエンティティに対するクエリには適していません。

7
James Westgate