web-dev-qa-db-ja.com

DELETE要求本文のRESTfulな代替

HTTP 1.1 specDELETE リクエストでallowメッセージ本文を許可しているようですが、定義されたセマンティクスがないため、サーバーはそれを無視する必要があることを示しているようです。

4.3メッセージ本文

サーバーは、要求に応じてメッセージ本文を読み取り、転送する必要があります。要求メソッドにエンティティ本体の定義済みセマンティクスが含まれていない場合、要求を処理するときにメッセージ本体を無視する必要があります。

SO以降のこのトピックに関するいくつかの関連する議論を既にレビューしました。

ほとんどの議論では、DELETEでメッセージ本文を提供することはallowedかもしれませんが、一般的には推奨されていません。

さらに、さまざまなHTTPクライアントライブラリの傾向に気付きました。これらのライブラリでは、DELETEでのリクエストボディをサポートするために、これらのライブラリの機能強化がますます記録されているようです。ほとんどのライブラリーは義務付けられているように見えますが、ときどき少し初期抵抗があります。

私のユースケースでは、DELETEに必要なメタデータをいくつか追加する必要があります(たとえば、削除に必要な他のメタデータとともに、削除の「理由」)。次のオプションを検討しましたが、どれも完全に適切であり、HTTP仕様やRESTベストプラクティスに沿っているとは限りません。

  • メッセージ本文-仕様では、DELETEのメッセージ本文にセマンティック値がないことを示しています。 HTTPクライアントでは完全にサポートされていません。標準的な慣行ではありません
  • カスタムHTTPヘッダー-カスタムヘッダーを要求することは、通常 標準プラクティス に対してです。それらを使用することは、APIの残りの部分と矛盾しますが、いずれもカスタムヘッダーを必要としません。さらに、悪いカスタムヘッダー値を示す良いHTTPレスポンスはありません(おそらく個別の質問)
  • 標準HTTPヘッダー-適切な標準ヘッダーはありません
  • クエリパラメータ-クエリパラメータを追加すると、削除されるRequest-URIが実際に変更されます。 標準プラクティス
  • POSTメソッド-(例:POST /resourceToDelete { deletemetadata })POSTは削除のセマンティックオプションではありません。 POSTは実際にoppositeアクションを表します(つまり、POSTはリソースの下位を作成しますが、リソースを削除する必要があります)
  • 複数のメソッド-DELETEリクエストを2つの操作に分割する(たとえば、PUT削除メタデータ、次にDELETE)アトミック操作を2つに分割し、一貫性のない状態を残す可能性があります。削除理由(および他の関連メタデータ)は、リソース表現自体の一部ではありません。

私の最初の好みは、おそらくメッセージ本文を使用することであり、2番目はカスタムHTTPヘッダーです。ただし、示されているように、これらのアプローチにはいくつかの欠点があります。

このような必要なメタデータをDELETE要求に含めるためのREST/HTTP標準に沿った推奨事項またはベストプラクティスはありますか?私が検討していない他の選択肢はありますか?

85
shelley

DELETEリクエストにメッセージ本文を使用しないという推奨事項にもかかわらず、このアプローチは特定のユースケースで適切な場合があります。これは、質問/回答に記載されている他のオプションを評価し、サービスの利用者と協力した後に使用したアプローチです。

メッセージ本文の使用は理想的ではありませんが、他のオプションはどれも完全には適合していません。リクエストボディDELETEを使用すると、DELETE操作に必要な追加のデータ/メタデータに関するセマンティクスを簡単かつ明確に追加できました。

私はまだ他の考えや議論を受け入れていますが、この質問のループを閉じたいと思っていました。このトピックに関する皆さんの考えと議論に感謝します!

40
shelley

あなたが望んでいるのは、純粋なDELETEではない2つのもののうちの1つです:

  1. 2つの操作があります削除理由のPUTとそれに続くDELETEのリソース。削除すると、リソースのコンテンツには誰もアクセスできなくなります。 「理由」には、削除されたリソースへのハイパーリンクを含めることはできません。または、
  2. リソースを変更しようとしていますDELETEメソッドを使用して、state=activeからstate=deletedに変更します。 state = deletedのリソースはメインAPIによって無視されますが、管理者またはデータベースにアクセスできる人には読み取り可能です。これは許可されています-DELETEは、リソースのバッキングデータを消去する必要はなく、そのURIで公開されているリソースを削除するだけです。

DELETEリクエストでメッセージ本文を必要とする操作は、最も一般的なPOSTと、メッセージ本文で必要なすべてのタスクを実行するDELETEに分割できます。 HTTPのセマンティクスを破る理由はありません。

12
Nicholas Shanks

あなたが持っている状況を考えると、私は次のアプローチのいずれかを取るでしょう:

  • PUTまたはPATCHを送信:削除理由が必要であるという性質により、削除操作は仮想的であると推測しています。したがって、それ自体はDELETE操作ではありませんが、PUT/PATCH操作を介したレコードの更新は有効なアプローチであると考えています。
  • クエリパラメータを使用:リソースURIは変更されていません。これも実際に有効なアプローチだと思います。リンクした質問は、クエリパラメータが欠落している場合に削除を許可しないことについて話していました。あなたの場合、クエリ文字列で理由が指定されていない場合、デフォルトの理由があります。リソースは引き続きresource/:idのままです。各理由のリソースのリンクヘッダーで検出可能にすることができます(それぞれにrelタグを付けて理由を識別します)。
  • 理由ごとに個別のエンドポイントを使用resource/:id/canceledのようなURLを使用します。これは実際にRequest-URIを変更し、RESTfulではありません。繰り返しになりますが、リンクヘッダーはこれを検出可能にします。

RESTは法律でも教義でもないことを忘れないでください。それをガイダンスと考えてください。したがって、問題のあるドメインのガイダンスに従わないことが理にかなっている場合は、従わないでください。 APIコンシューマーに差異が通知されていることを確認してください。

7
codeprogression

URI階層の一部として必要なメタデータを含めることをお勧めします。例(単純):

開始日と終了日を本文またはクエリパラメータとして渡す代わりに、日付範囲に基づいてエントリを削除する必要がある場合は、必要な情報をURIの一部として渡すようにURIを構成します。

例えば.

DELETE /entries/range/01012012/31122012-2012年1月1日から2012年12月31日までのすべてのエントリを削除します

お役に立てれば。

0
Suresh Kumar