web-dev-qa-db-ja.com

ツリー階層の場合、REST URLスキーマはどのように見えるべきですか?

私が店、店の棚、そして棚の上の製品を持っていると仮定しましょう。したがって、店舗の棚にある商品のリストを取得するには、次のリクエストを使用します。

GET http://server/stores/123/shelves/456/products

ここから、どのようにして個々の製品を入手しますか?使用する必要があります:

GET http://server/products/789

または:

GET http://server/stores/123/shelves/456/products/789

最初の方法はより簡潔です。商品のリストを取得したら、特定の商品の詳細を表示するだけであれば、どのストアに属しているかは気にしないからです。ただし、特定の店舗の特定の棚の商品を表示しているため、2番目の方法の方が論理的です。

同様に、PUT/DELETE操作はどうですか?

DELETE http://server/stores/123/shelves/456/products/789

または:

DELETE http://server/products/789

このようなツリー階層のスキーマを設計する正しい方法は何でしょうか?

P.S. RESTアーキテクチャについて誤解している場合は、これを改善する方法の例を教えてください。「RESTはCRUDではない」や「RESTはCRUDではない」と言うのが好きな人が多すぎますRPCではありません」の場合、適切なRESTful設計の説明や例はまったく提供されません。

27
Daniel T.

URL構造に基づいてREST apiを設計しないでください。 ここ は、REST api。

どのリソースにどのリンクが含まれるかを議論せずにRESTインターフェースを定義しようとすると、RPCインターフェースについて議論し、パラメーターと戻り値を無視するようなものです。

2
Darrel Miller

RESTful URI設計への2つのアプローチに注目しました:階層的およびフィルター処理済み

階層は過度に冗長であり、冗長なエンドポイント(DRYではない)の可能性があり、本当に関心のあるリソースの状態を偽装しているように感じます(結局のところ、REST =representational状態転送)。

シンプルなURIが好き

シンプルでエレガント。次のようなURI構造を選択します

GET http://server/products/789

製品リソースの状態に興味があるからです。

特定の店舗の特定の棚に属するすべての商品が必要な場合は、

GET http://server/products?store=123&shelf=456

特定の棚の特定の店舗で商品を作成したい場合は、投稿します

{
    product: {
        store: 123,
        shelf: 456,
        name: "test product"
    }
}

via

POST http://server/products

最終的には、トマト、トマトです

RESTは一方を他方の上に置く必要はありません。ただし、私自身の経験では、渡されるパラメーターに基づいてエンティティを多くの異なるエンドポイントにマップするよりも、単一のエンティティを単一のエンドポイントにマップするRESTful APIを使用する方が効率的です(例:iOSのRestKitオブジェクトマッピング)。

RESTについて

RESTに関する限り、これはプロトコルではなく、RFCもありません。 CRUDアクションを実装する方法としてHTTP/1.1 RFCと密接に関連していますが、多くのソフトウェアエンジニアは、RESTはHTTPに依存しないと考えています。私は同意せず、推測などを検討します。 UCIのRoyFielding( http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm )による元の論文は、RESTおよびHTTP/1.1。このトピックに関するロイの意見もお楽しみいただけます: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

RESTで定義された原則は他のプロトコルにも適用できますが、RESTはインターネット用に構築されており、HTTPはワールドワイドウェブ用のプロトコル。

RESTとRPC

[〜#〜] rpc [〜#〜]はすべてリモート関数を呼び出すことであり、動詞です- centric

[〜#〜] rest [〜#〜]は、CRUD操作が特定のデータにどのように適用されるかに応じて、CRUD規則を使用してデータに作用することです。データ型であり、名詞中心です。

RESTまたはRPCでも同じことができますが、RESTはDRYの原則に従います。これは、すべてのURIに対して実行できるためです。 4つのアクションに対して、RPCはアクションごとにエンドポイントを必要とします。

PS

これの多くは私の意見であり、私の経験に基づいていますが、RESTfulURIスキーマを最も効率的に設計する方法に光を当てることを願っています。いつものように、あなたの特定の目標とニーズはあなたの選択に影響を与えますが、単純さは常に目指すべき良い目標です。

17
Brenden

製品の作成は、POST to

http://server/product

製品の更新は、

http://server/product/$id

製品を入手することは、

http://server/product/$id

製品の削除は、単にDELETEする必要があります

http://server/product/$id

より単純なURI構造からより多くの機能を引き出すには、そこにあるhttpメソッドを使用する必要があります。製品を作成するために必要に応じて店舗と棚を渡す必要がある場合は、それらをPOST(または棚を変更する場合はPUT)の本体に渡す必要があります。

誰かがhttp://server/product/$idにGETを実行すると、ある種のxml/json応答が返されますよね?それはどのように見えますか?作成または更新の受信データは、リクエストの本文に同じ方法でPOSTまたはPUTする必要があります。これが、URIを介さずに、店舗と棚を通過する方法です。 uriはできるだけ単純で、http動詞を使用して機能を区別し、リソース(製品)を指す必要があります。

シェルフ23の内容を取得できるようにする場合は、GETを実行します。

http://server/shelf/23

これを行うと、シェルフデータと製品uriへのリンクを含む製品要素のコレクションを含むjson/xml /カスタムメディアタイプドキュメントが返されます。

製品23をある棚から別の棚に移動できるようにしたい場合は、次のようにPUTを実行します。

http://server/product/23 

PUTの本体には、選択した表現の製品がありますが、棚が更新されています。

システム全体の機能を扱っているのではなく、リソース(製品、棚、店舗)に焦点を当て、http動詞を使用してそれらを宇宙に公開しているため、最初は奇妙な考え方です。

6
Matthew Daumen

商品は複数の店舗または複数の棚(カテゴリ?)にある可能性があるため、階層内の位置に関係なく、各商品に一意の番号を付けます。次に、フラットな製品番号を使用します。これにより、たとえば一部の商品がストアに移動された場合にAPIがより安定します。

つまり、APIに不要な冗長性を追加しないでください。棚リストを取得するにはストアIDで十分であり、商品リストでは棚IDで十分です...など。

2
Lucero

さまざまなユースケースを構築しようとしているようですが、すべてが1つのスーパーサービスに組み込まれています。それを打ち破ったほうがいいでしょう。

http://server/product_info/123123 or http://server/product_info?product=123123
http://server/product_inventory?store=123&shelf=345

次に、以下をサポートすることもできます。

http://server/product_inventory?store=123

次に、PUTとDELETEは、在庫の変更や新製品の追加に適しています。

0
mlathe