RESTfulサービスでの非CRUD操作


106

非CRUD操作をRESTfulサービスに追加する「RESTful」な方法は何ですか?次のようなレコードへのCRUDアクセスを許可するサービスがあるとします。

GET /api/car/123           <- Returns information for the Car object with ID 123
POST /api/car              <- Creates a new car (with properties in the request)
PUT /api/car/123           <- Updates car 123 (with properties in the request)
DELETE /api/car/123        <- Deletes car 123    
POST /api/car/123/wheel/   <- Creates a wheel and associates it to car 123

車の色を変更したい場合POST /api/car/123は、単純に新しい色のPOST変数を含めます。

しかし、車を購入したいとします。その操作は、単に「ユーザー」レコードの「所有車」プロパティを更新するよりも複雑です。POST /api/car/123/purchase「購入」が基本的にメソッド名であるのようなことを単純に行うのはRESTful ですか?または、PURCHASE代わりになどのカスタムHTTP動詞を使用する必要がありPOSTますか?

または、非CRUD操作は完全にRESTの範囲外ですか?


5
車の色を変更する場合はPATCH /api/car/123、カラーパラメータを使用PUT /api/car/123して送信するか、車オブジェクト全体を使用して送信することをお勧めします。POSTは、新しい車を作成していると推測し、URLの末尾にIDを含めないでください
RonnyKnoxville

回答:


65

RESTful辞書のビジネスエンティティまたはリソースとして購入を考えてください。そうは言っても、実際に購入すると、新しいリソースが作成されます。そう:

POST /api/purchase

新規注文します。詳細(ユーザー、車など)は、このアドレスに送信されるコンテンツ内のID(またはURI)で参照する必要があります。

車の注文がデータベースの単なるINSERTではないことは問題ではありません。実際、RESTはデータベーステーブルをCRUD操作として公開することではありません。論理的な観点からは、注文(購入)を作成しますが、サーバー側は必要な数の処理ステップを自由に実行できます。

HTTPプロトコルをさらに悪用することもできます。Locationヘッダーを使用して、新しく作成された注文へのリンクを返し、HTTP応答コードを慎重に選択して、問題(サーバー側またはクライアント側)についてユーザーに通知します。


3
RESTはすべてリソースの状態を操作することであり、すべてのビジネスオペレーションは状態CRUDオペレーションにマップする必要があります。ハードビジネスオペレーションのセマンティクスが必要場合は、SOAP を使用する必要があります(SOAPは実際にはメッセージパッシングですが、通常は要求/応答オペレーションで構成されます)。
Tomasz Nurkiewicz

23
「リソースとして購入する」デザインはすっきりします。リソースが「ビール」であり、サーバーにそれを飲ませたい場合はどうすればよいでしょうか(それは私のためでした、私はきっとそれをGETします;))。「ドリンクアクション」をリソースと見なす必要があります?!..または「ビールを飲む」、ハードビジネスオペレーションですか。より真剣に、RESTfulな設計はアクションをリソースとして考えることについてのものですか?!..
Myobis

2
RESTサービスを通じて「注文を承認」をどのように公開しますか?@TomaszNurkiewiczは、CRUDの方法ではきちんと実行できないものにはSOAPが提供する操作セマンティクスが必要になるという点で正しいと思います。「購入注文の承認」が独自のモデル/エンティティでない限り。たとえば、POST / po-approval(POの詳細がリクエストに含まれています)。
mydoghasworms 2014

2
RESTクライアントの観点からは、「注文の承認」は注文の別の更新である必要があります。たとえば、「承認済み」を「true」に変更して、更新をサーバーに送信します。サーバーはおそらく一連のチェックを行う必要があり、おそらく他の一連のリソースを更新/作成する必要があります。しかし、それはサーバーの問題であり、クライアントには見えません。
AVee 2014年

2
@antinome:RESTを実行していない場合は、「クライアントがこれを知っているとしましょう」(ただし、RESTは有効で賢明なソフトウェアである可能性があります)。RESTは、そのようなことを知らないクライアントを作成し、サーバーの動作が変化しても機能するクライアントを作成できるように設計されています。あなたがやろうとしているのは、古典的なRPCです。RESTに適合するようにアプローチを確認するか、RPCを実行していてSOAPのようなRPC向けのプロトコルを使用していることを受け入れる必要があります。RESTはRPCにならないように一生懸命努力しているため、RPCが必要な場合にRPCが適していることは決してありません。
AVee 14

15

私が理解しているRESTfulな方法は、新しいHTTP動詞は必要ないということです。何をすべきかを意味する名詞がどこかにあります。

車を購入しますか?まあそれではない

POST /api/order

2
べき等なので、リソースの更新に PUTは使用されませんか?つまり、何度でも呼び出すことができますが、重要なのは最初/最後の呼び出しだけです。一方、POSTはリソースの作成に使用され、2回呼び出すと実際には2つ作成されます。
Tomasz Nurkiewicz

1
@トーマス、はい、タイプミス。ただし、原則は重要です。私たちは、新しい動詞を必要とせずに、新しいもの、命令を扱っています。
djna

5

あなたが本当にやっていることは、注文を作成することです。したがって、注文用の別のリソースを追加して投稿し、注文プロセス中にそこに入れます。

メソッドの呼び出しではなく、リソースの観点から考えてください。

注文を確定するには、おそらくPOST / api / order // completeまたは同様の何かを行います。


3

REST APIは、セマンティクスを提供するだけでなく、はるかに多くの点で役立つと思います。したがって、RPC操作スタイルでより理にかなっているように見える呼び出しがあるからといって、RPCスタイルを選択することはできません。例は、2つの場所の間のルートを検索するgoogle maps apiです。次のようになります:http : //maps.googleapis.com/maps/api/directions/json?origin=Jakkur&destination=Hebbal

彼らはそれを「findDirections」(動詞)と呼んで、操作として扱ったかもしれません。むしろ、彼らは「方向」(名詞)をリソースとして作成し、方向を見つけるリソースをクエリとして扱いました(内部的には、方向と呼ばれる実際のリソースはなく、ビジネスロジックによって実装され、パラメーターに基づいて方向を見つけることができます)。


それは悪い例です。この場合、方向(可能なすべての方向、それらの数は無限)はリソースであり、パラメーターは単なるフィルターです。しかし、あなたは、フィルタのみGET操作の感覚や順序を置くことになりますと、これに「購入」を行うか、それがデータを変更する操作ですキャンセルすることはできません
ツェン

2
購入は、注文が作成されたことを示すために本文にjsonを含む/ orderへのPOSTです。cancelは/ orderへのPUTであり、jsonが注文状態の変化を伝え、これがべき等更新であることを示します。まだリソース形式で表現できない操作に出くわします。したがって、そのような例を見てみたいと思います
Maruthi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.