8

したがって、HTTP 仕様では、HTTP PUT と DELETE は冪等でなければならないと述べています。つまり、同じボディを持つ同じ URL への複数の PUT リクエストが、サーバーに追加の副作用をもたらすべきではありません。複数の HTTP DELETE についても同様です。2 つ以上の DELETE リクエストが同じ URL に送信された場合、2 番目 (または 3 番目など) のリクエストは、リソースが既に削除されていることを示すエラーを返すべきではありません。

しかし、DELETE が処理された後の URI への PUT 要求はどうでしょうか? 404を返す必要がありますか?

たとえば、次のリクエストがこの順序で実行されるとします。

  • POST /api/items -itemリソースを作成し、HTTP 201 と URI /api/items/6 を返します
  • itemPUT /api/items/6 - #6に関連付けられたデータを更新します
  • PUT /api/items/6 - リクエストの本文が前の PUT と同じである限り、副作用はありません
  • DELETE /api/items/6 - item#6 を削除し、HTTP 202 を返します
  • DELETE /api/items/6 - 副作用はなく、HTTP 202 も返します
  • GET /api/items/6 - これで 404 が返されます
  • PUT /api/items/6 -ここで何が起こるべきか? 404? 409? 他の何か?

では、PUT は 404 を取得して返すことと一致する必要がありますか、または @CodeCaster が示唆するように、409 の方が適切でしょうか?

4

2 に答える 2

11

RFC 2616、セクション 9.6、PUT:

POST 要求と PUT 要求の根本的な違いは、Request-URI の異なる意味に反映されています。POST 要求の URI は、含まれるエンティティを処理するリソースを識別します。そのリソースは、データを受け入れるプロセス、他のプロトコルへのゲートウェイ、または注釈を受け入れる別のエンティティである可能性があります。対照的に、PUT リクエストの URI は、リクエストに含まれるエンティティを識別します。ユーザー エージェントは、意図されている URI を認識しており、サーバーはリクエストを他のリソースに適用しようとしてはなりません。

と:

Request-URI でリソースを作成または変更できなかった場合は、問題の性質を反映した適切なエラー応答を与える必要があります。

したがって、「適切」と定義するには、400 シリーズを調べて、クライアント エラーがあることを示します。まず、無関係なものを削除します。

  • 400 Bad Request : 構文が正しくないため、サーバーがリクエストを理解できませんでした。
  • 401 Unauthorized : リクエストにはユーザー認証が必要です。
  • 402 Payment Required : このコードは将来の使用のために予約されています。
  • 406 Not Acceptable : リクエストで識別されたリソース [...] リクエストで送信された Accept ヘッダーによると、受け入れられません。
  • 407 Proxy Authentication Required : このコード [...] は、クライアントが最初にプロキシで自分自身を認証する必要があることを示します。
  • 408 Request Timeout : クライアントは、サーバーが待機する準備ができている時間内に要求を生成しませんでした。
  • 411 Length Required : サーバーは、Content-Length が定義されていない要求の受け入れを拒否します。

それで、どれを使うことができますか?

403禁止します

サーバーは要求を理解しましたが、要求を満たすことを拒否しています。承認は役に立たず、要求を繰り返すべきではありません。

この説明は、通常はパーミッション関連のコンテキストで使用されますが、実際にはかなり適切です (次のように: YOU may not ...)。

404お探しのページが見つかりませんでした

サーバーは Request-URI に一致するものを見つけられませんでした。状態が一時的なものか永続的なものかは示されていません。410 (Gone) ステータス コードは、古いリソースが永続的に利用できず、転送アドレスがないことを内部的に構成可能なメカニズムを通じてサーバーが認識している場合に使用する必要があります。このステータス コードは、サーバーが要求が拒否された理由を正確に明らかにしたくない場合、または他の応答が適用できない場合に一般的に使用されます。

これも、特に最後の行。

405メソッドは許可されていません

Request-URI で識別されるリソースに対して、Request-Line で指定されたメソッドは許可されていません。応答には、要求されたリソースの有効なメソッドのリストを含む Allow ヘッダーが含まれている必要があります。

現時点ではこのリソースでメソッドを実行したくないため、応答できる有効なメソッドがないため、405 を返すことはできません。

409 紛争

競合は、PUT 要求への応答で発生する可能性が最も高くなります。たとえば、バージョニングが使用されていて、PUT されるエンティティに、以前の (サードパーティの) リクエストによって行われたものと競合するリソースへの変更が含まれていた場合、サーバーは 409 レスポンスを使用して、リクエストを完了できないことを示す可能性があります。 . この場合、応答エンティティには、応答の Content-Type によって定義された形式で、2 つのバージョン間の相違点のリストが含まれている可能性があります。

しかし、これは URI に既にリソースがあることを前提としています (何も競合しないのはどうしてでしょうか?)。

410 ゴーン

要求されたリソースはサーバーで使用できなくなり、転送先アドレスも不明です。この状態は永続的であると考えられています。リンク編集機能を持つクライアントは、ユーザーの承認後に Request-URI への参照を削除する必要があります。状態が永続的かどうかをサーバーが認識していないか、判断する機能がない場合は、代わりにステータス コード 404 (Not Found) を使用する必要があります。

これも一理あります。


私はこの投稿を数回編集し、「410 または 404 を使用する」と主張したときに受け入れられましたが、RFC では 403 が権限に関連する必要があるとは述べていないため、403 も適用可能であると考えています (しかし、一般的な Web サーバーではそのように実装されているようです)。他のすべての 400 コードを削除したと思いますが、お気軽にコメントしてください (反対票を投じる前に)。

于 2012-10-29T16:02:40.903 に答える
0

あなたの質問には、PUTが成功するためにリソースが存在しなければならないという、明言されていない、仮定された前提があります。 これは有効な仮定ではありません。

仕様の関連部分(RFC2616)は次のように述べています。

ユーザーエージェントはどのURIが意図されているかを知っており、サーバーは他のリソースにリクエストを適用しようとしてはなりません(MUSTNOT)。

仕様には、「参照されたURIへのPUTが成功するには、参照されたURIのオブジェクトがすでに存在している必要があります」とは記載されていません。


簡単な例は、RESTを介して実装されたWebストアです。 GET指定されたパスにあるオブジェクトの表現を返し、指定されたパスにDELETEあるアイテムを削除します。それらは簡単です。しかし、POSTとPUTを理解するのはそれほど難しくありません。POST何でもできますが、1回の使用でPOST、クライアントが指定するコンテナーにオブジェクトを作成し、サーバーがそのコンテナー内に新しく作成されたオブジェクトのURIを返すようにします。PUTより制限されています。これは、サーバーに特定のURIでのオブジェクトの表現を提供します。オブジェクトはすでに存在する場合と存在しない場合があります。PUTREPLACEの同義語ではありません。

私の意見では、409または410はPUTにとって間違っています。ただし、コンテナー自体(入れようとしているもの)が存在しない場合を除きます。

したがって:

POST /container
   ==> returns 200 with `Location:/container/resource-12345`

PUT /container/resource-98928
   ==> returns 201 CREATED or 200 OK

PUT /this-container-does-not-exist/resource-22828282
   --> returns 400

もちろん、サーバーでこれらのPUTセマンティクスを許可するかどうかは、あなた次第です。しかし、仕様には、クライアントがPUTしているリソースのURIを提供することを許可してはならないということは何もありません。

于 2012-10-30T18:55:01.080 に答える