HTTP DELETE要求を発行する場合、要求URIは削除するリソースを完全に識別する必要があります。ただし、リクエストのエンティティボディの一部として追加のメタデータを追加することはできますか?
HTTP DELETE要求を発行する場合、要求URIは削除するリソースを完全に識別する必要があります。ただし、リクエストのエンティティボディの一部として追加のメタデータを追加することはできますか?
回答:
仕様は明示的にそれを禁止したり落胆させたりしないので、私はそれが許可されていると言う傾向があります。
マイクロソフトはそれを同じように見ています(聴衆の中でつぶやくのを聞くことができます)、彼らはADO.NETデータサービスフレームワークのDELETEメソッドに関するMSDNの記事で述べています:
DELETEリクエストにエンティティボディが含まれている場合、ボディは無視されます[...]
さらに、RFC2616(HTTP 1.1)が要求に関して述べなければならないことは次のとおりです。
Content-Length
またはTransfer-Encoding
ヘッダーを含めることで通知されます(セクション4.3)応答の場合、これは定義されています:
HTTP 1.1仕様(RFC 7231)の最新の更新では、DELETEリクエストでエンティティ本体を明示的に許可しています。
DELETE要求メッセージ内のペイロードには、意味が定義されていません。DELETEリクエストでペイロード本体を送信すると、一部の既存の実装がリクエストを拒否する可能性があります。
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
下位互換性の警告が付属しているため、次の標準が言っていることを示唆しています。DELETE
ボディを持つことができます `。
A payload within a DELETE request message has no defined semantics
。だから体は許される。
TomcatとJettyの一部のバージョンでは、エンティティボディが存在しても無視されます。あなたがそれを受け取るつもりなら、それは迷惑になることができます。
削除リクエストで本文を使用する1つの理由は、楽観的同時実行制御のためです。
レコードのバージョン1を読み取ります。
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
同僚がレコードのバージョン1を読み取ります。
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
同僚がレコードを変更してデータベースを更新し、バージョンが2に更新されます。
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
あなたはレコードを削除しようとします:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
楽観的ロック例外が発生するはずです。レコードをもう一度読んで、それが重要であることを確認し、削除しないでください。
これを使用するもう1つの理由は、一度に複数のレコードを削除することです(たとえば、行選択チェックボックスのあるグリッド)。
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
各メッセージには独自のバージョンがあることに注意してください。たぶん、複数のヘッダーを使用して複数のバージョンを指定できるかもしれませんが、Georgeによって、これはより単純ではるかに便利です。
これはTomcat(7.0.52)とSpring MVC(4.05)で動作しますが、おそらく以前のバージョンでも動作します。
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
またはEtag
、それが目的です)。
ように私には見えるRFC 2616はこれを指定していません。
セクション4.3から:
リクエスト内のメッセージ本文の存在は、リクエストのメッセージヘッダーにContent-LengthまたはTransfer-Encodingヘッダーフィールドを含めることで通知されます。リクエストメソッドの仕様(セクション5.1.1)がリクエストでのエンティティボディの送信を許可しない場合、メッセージボディをリクエストに含めることはできません。サーバーは、あらゆるリクエストでメッセージ本文を読み取って転送する必要があります。リクエストメソッドにエンティティボディの定義されたセマンティクスが含まれていない場合、リクエストを処理するときにメッセージボディを無視する必要があります(SHOULD)。
そしてセクション9.7:
DELETEメソッドは、起点サーバーがRequest-URIで識別されるリソースを削除することを要求します。このメソッドは、オリジンサーバーでの人間の介入(または他の手段)によってオーバーライドされる場合があります。オリジンサーバーから返されたステータスコードがアクションが正常に完了したことを示している場合でも、クライアントは操作が実行されたことを保証できません。ただし、サーバーは、応答が与えられたときにリソースを削除するか、アクセスできない場所に移動することを意図していない限り、成功を示すべきではありません(SHOULD NOT)。
成功した応答は、応答にステータスを説明するエンティティが含まれている場合は200(OK)、アクションがまだ実行されていない場合は202(承認済み)、アクションが実行されているが応答に含まれていない場合は204(コンテンツなし)であるべきです(SHOULD)。エンティティ。
リクエストがキャッシュを通過し、Request-URIが現在キャッシュされている1つ以上のエンティティを識別する場合、それらのエントリは古いものとして扱われる必要があります(SHOULD)。このメソッドへの応答はキャッシュできません。
そのため、明示的に許可または禁止されておらず、途中でプロキシがメッセージ本文を削除する可能性があります(ただし、それを読み取って転送する必要があります)。
ヘッドアップです。DELETEリクエストで本文を指定し、Google Cloud HTTPSロードバランサーを使用している場合、400エラーでリクエストが拒否されます。私は頭を壁にぶつけて、Googleが何らかの理由で、本文を含むDELETE要求は不正な形式の要求であると考えていることを発見しました。
for whatever reason
-仕様にそのように記載されているため:P
DELETE
は後者です。
ElasticSearchがこれを使用しているようです:https ://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
つまり、Nettyはこれをサポートしています。
コメントで言及されているように、もうそうではないかもしれません
HTTPメーリングリストのロイフィールディングは、httpメーリングリストhttps://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.htmlで次のように明言しています :
GET / DELETE本文は、リクエストの処理または解釈に影響を与えることは絶対に禁止されています
これは、本体がサーバーの動作を変更してはならないことを意味します。次に彼は追加します:
メッセージのフレーミングを維持するために受信したバイトを読み取って破棄する必要性は別として。
そして最後に、身体を禁じない理由:
ボディの送信を禁止しなかった唯一の理由は、ボディが送信されないことを想定した遅延実装につながるためです。
したがって、クライアントはペイロードボディを送信できますが、サーバーはそれをドロップし、APIはこれらのリクエストのペイロードボディのセマンティクスを定義しないでください。
これは定義されていません。
DELETE要求メッセージ内のペイロードには、意味が定義されていません。DELETEリクエストでペイロード本体を送信すると、一部の既存の実装がリクエストを拒否する可能性があります。
https://tools.ietf.org/html/rfc7231#page-29
本文でDELETEを使用するのは危険です... RESTよりもリスト操作の場合は、このアプローチを好みます。
定期的な運用
GET / objects / すべてのオブジェクトを取得します
GET / object / ID 指定されたIDのオブジェクトを取得します
POST / objects 新しいオブジェクトを追加します
PUT / object / ID 指定されたIDのオブジェクトを追加し、オブジェクトを更新します
DELETE / object / ID 指定されたIDのオブジェクトを削除します
すべてのカスタムアクションはPOSTです
POST / objects / addList 本文に含まれるオブジェクトのリストまたは配列を追加します
POST / objects / deleteList 本文に含まれるオブジェクトのリストを削除します
POST / objects / customQuery 本文のカスタムクエリに基づいてリストを作成します
クライアントが拡張操作をサポートしていない場合、通常の方法で動作できます。
POST
特にLocationヘッダーのコンテキストでは、POST応答のセマンティクスが不明確であるため、a を使用することは、新しいリソースを作成するための適切なRESTy方法ではありません。基本的にHTTPを残し、RPCをスタックします。適切な「HTTP / RESTの方法」はPUT
、If-None-Match: *
ヘッダーを使用してリソースを作成することです(または適切なHTTPメソッドを指定する、MKCOL
などを参照)。
これに対する良い答えは投稿されていないと思いますが、既存の答えについては素晴らしいコメントがたくさんあります。これらのコメントの要点を新しい答えに引き上げます。
RFC7231のこの段落は数回引用されていますが、それを要約しています。
DELETE要求メッセージ内のペイロードには、意味が定義されていません。DELETEリクエストでペイロード本体を送信すると、一部の既存の実装がリクエストを拒否する可能性があります。
他の答えから逃したのはその含意でした。はい、DELETE
リクエストに本文を含めることはできますが、意味的には意味がありません。これが実際に意味することはDELETE
、リクエスト本文を使用してリクエストを発行することは、意味的にはリクエスト本文を含めないことと同じです。
リクエストボディを含めてもリクエストには影響がないため、含めても意味がありません。
tl; dr:技術的にはDELETE
リクエスト本文を含むリクエストが許可されますが、そうすることは決して役に立ちません。
誰かがこの問題のテストを実行している場合、それは普遍的にサポートされていません。
私は現在Sahi Proでテストしていますが、http DELETE呼び出しにより、提供された本文データ(エンドポイントの設計に従って大量に削除するIDの大きなリスト)が取り除かれていることは明らかです。
私は何度か彼らと連絡を取り、3つの個別のパッケージのパッケージ、画像、ログを送って彼らが確認できるようにしましたが、彼らはまだこれを確認していません。パッチが失敗し、後でサポートが電話に出られなかったため、確実な答えが得られません。
Sahiはこれをサポートしていないと思います。他の多くのツールがスイートに続くと思います。
以下のGitHUbのURLが答えを得るのに役立ちます。実際、TomcatのようなApplication Server、WeblogicはリクエストペイロードによるHTTP.DELETE呼び出しを拒否しています。これらすべてを念頭に置いて、私はgithubに例を追加しました。