web-dev-qa-db-ja.com

同じリソースでPUTとPOSTを組み合わせる

プロセスとして修飾できると思うリソースRequestRequestがあります。 OrderRequestは、create of updateにすることができます。同じ注文リクエストを2回作成することは望ましくないため、作成はべき等でなければなりません。同時に、POSTはべき等ではなく、常に同じ結果を返すとは限りません。クライアント側で生成されたIDとサーバー側で生成されたIDを組み合わせて使用​​しています。 createが実行されると、クライアント側で生成されたIDが使用されるため、次のようになります。

PUT/orders/clientGeneratedID

また、使用可能なサーバー生成IDも返します。 clientGeneratedtIDがあることは、注文に関連付けられた「ディーラー注文」があることも意味するため、2つのIDには微妙な違いがあります。

作成された変更は、clientGeneratedIDまたはサーバー生成IDを介して変更されます。

POST/orders/{clientGeneratedIDまたはserverGeneratedID}/modifications

さまざまな投稿を読むと、作成されるものとPOSTについて、PUTUPDATEについて混乱があることがわかります。

私の理解では、IDとURLを指定しているので、createの正しい動詞はPUTです。同時に、私はプロセスを作成しているので、PUTpdateである必要があることは、私には正しく聞こえません。更新にPUTを使用するための前提条件であるリソースを完全に置き換えているわけではありません。したがって、POSTを使用することにしました。

そのような方法でPUTPOSTの両方を持っているのは間違っていますか?私はそれを正しくやっていますか?べき等のPOSTを作成できることを理解しています。しかし、PUTまたはPOSTのいずれかを使用する必要があるという一般的なガイドラインはありますが、組み合わせないでください。逆にPUTcreateおよびPOSTpdateで使用するという事実はどうですか? =?

2

PUTの設計については、ほとんど一緒にいます。クライアントは、指定した特定のIDに対してPUTを実行します。リソースが存在しない場合は、作成して201応答コードを返します。問題は、誰かがその同じリソースに対して再度PUTを試行するとどうなるかです。標準のPUTセマンティクスは、提供されている新しいコンテンツでそこにあるものを上書きすることですが、これは許可しない方がいいと思います。リソースを置き換えることができないという詳細を含むエラー(400は機能するはずです)を返すことができます。

余談ですが、PUTべき等性の要点は、PUTの処理中にエラーが発生した場合に、物を壊すことを恐れずに呼び出しを繰り返すことができるようにすることです。これは、(理論的には)クライアントライブラリが成功するまでループでPUTを呼び出すことができることを意味します。 POSTでは、呼び出しごとに異なるリソースが作成される可能性があるため、これを行うことはできません。したがって、本当に凝ったものになり、内容がすでにそこにあるものと同じである場合、200 OKを返し、何かが別のものと注文を置き換えようとしている場合にのみエラーを返すことができます。

次に、POST操作に進みます。「更新にPUTを使用するための前提条件であるリソースを完全に置き換えているわけではありません。そのため、POSTを使用することにしました。」

ここにはいくつかのオプションがあります。 1つは、PATCH動詞を紹介することです。この動詞は、リソースへの部分的な変更を可能にするためのものです。個人的には、これがあなたのデザインにとって良い選択である理由を本当に理解していない限り、多かれ少なかれあなたが行っている変換を指定するためのミニ言語が必要であることを意味するので、それを避けるべきだと思います。

私がフォローしている場合、POSTはここで意味があると思います。 POSTの目的は、基本的に新しいリソースを作成しようとすることです。この場合、新しいリソースは注文の「変更」です。これはビジネスではかなり標準的です。注文の変更は、独自のトランザクションとして扱われます。元の注文の履歴とすべての変更はすべて重要な情報です。これを「正しい方法」で行うことが心配な場合は、変更が成功するたびに新しいURIを割り当てる必要があります(例:/ orders/bub123/modifications/001)。

しかし、PUTまたはPOSTのいずれかを使用する必要があるという一般的なガイドラインがありますが、組み合わせないでください。また、作成およびPOST更新しますか?

PUTとPOSTをさまざまな方法で組み合わせることができます。選択しなければならないというルールは絶対にありません。それはセマンティクスが異なるだけです。おそらく有用な例を示すと、 /orders/に対してPOSTをサポートします。この場合の違いは、クライアントが指定したIDを割り当てないことです。サーバーは、98765などの新しいIDを作成し、対応するURI /orders/98765を返します。置き換えを許可する場合、そのURIはPUT呼び出しを受け入れることができます。

POSTは更新用ではなく、ここでは更新に使用されていないと主張します。一般的な意味で、それは注文の更新であるため、あなたの考えを理解します。しかし、RESTの意味で、ここでの設計は実際には注文の子リソースを作成しています。元の注文内容はそのままですが、変更が添付されています。かなり賢明な設計だと思いますそして、それはあなたをつまずかせている命名法にすぎません。

2
JimmyJames

ClientGeneratedIDとserverGeneratedIDの両方のリソース識別子を持つというあいまいなセマンティクスを回避します。クライアントが生成したIDがリクエスト/オブジェクトの本文に含まれている場合は、より明確なセマンティクスを実現します。

次に、POSTセマンティクスに移動できます。ここで、POSTは成功してserverGeneratedIDを返します(通常はロケーションヘッダーにあります)。そうでない場合。サーバー上に何かを作成しており、clientGeneratedIDはクライアントがサーバーに保存したいものであると想定していますが、サーバーはclientGeneratedIDを理解する必要がなく、clientGeneratedIDによって参照される以前のデータはありません。

同じclientGeneratedIDを持つ他のオブジェクトの存在を確認し、a、err、競合が存在する場合は409 Conflictを返すことができます。

RESTには、多くのユースケースに対する明確な答えがありません。私はあなたができる最善の決定をし、次に進むことをお勧めします。 API(または可能であればAPIのグループ)内で一貫性を保つだけです。 RESTで指定されていない、またはあいまいな項目に関する私のグループの20種類の規制のリストがあります。たとえば、APIのバージョン管理。

1
Martin K