web-dev-qa-db-ja.com

サーバーのビジネスロジックエラーを表すためにHTTPステータスコードを使用する必要がありますか?

私は、クライアント(ブラウザーのJS)がサーバーと通信するためのいくつかのAPI設計の岐路に立っています。安全ロックが有効になっているためにアクションが失敗したことを表すには、HTTP 409 Conflictを使用します。 satefyロックは、開発者がお客様の生産システムを誤って変更することを防ぎます。特定のAPI呼び出しが失敗した理由を示すために、クライアントで409sをもう少し優雅に処理する必要があります。

私の解決策は、409が原因で何かが失敗したときにクライアントに通知を表示するAJAX呼び出しのいずれかの失敗ハンドラーをラップすることでした-これはすべて問題なく、他の4XXおよび5XXと一緒にうまく機能します同じメカニズムを使用するエラー。

ビジネスロジックエラーが発生したときにルートハンドラーの1つが409で応答するという問題が発生しました-my AJAX=ラッパーは安全ロックがオンであることを報告しますが、クライアントの既存の障害ハンドラーは何を報告します(それは考えます)問題は応答の本文に基づいています。簡単な解決策は、ハンドラーの応答または安全ロックを表すために使用するステータスコードを変更することです。

どちらが私を交差点に連れて行きます:HTTPステータスコードはビジネスロジックエラーを表すために使用する必要がありますか? この質問 は私が直面している同じ問題に対処しますが、それほど大きな牽引力は得られませんでした。リンクされた回答で示唆されているように、私は適切なボディでHTTP 200 OKを使用して、ビジネスロジック内の障害を表すことに傾倒しています。

ここに誰か強い意見はありますか?これが失敗を表す間違った方法であると私に納得させることができる人はいますか?

22
Joe Shanahan

Kasey 要点をカバーしています。

任意のWeb APIの重要なアイデア:ドメインをドキュメントストアのように見せるようにします。 GET/PUT/POST/DELETEなどは、すべてドキュメントストアと対話する方法です。

したがって、a使用するコードについての考え方は、ドキュメントストアでの類似の操作が何であるか、およびこの失敗がどのようになるかを理解することですそのアナログ。

2xxは完全に不適切

ステータスコードの2xx(成功)クラスは、クライアントの要求が正常に受信、理解、および受け入れられたことを示します。

5xxも不適切

ステータスコードの5xx(サーバーエラー)クラスは、サーバーがエラーを認識していることを示します

この場合、サーバーは間違いを犯していません。現時点では、そのリソースをそのように変更することは想定されていません。

ビジネスロジックエラー(現時点では、ビジネスインバリアントが提案された編集を許可していないことを意味します)はおそらく 409 です。

409(競合)ステータスコードは、ターゲットリソースの現在の状態との競合が原因で要求を完了できなかったことを示します。このコードは、ユーザーが競合を解決してリクエストを再送信できる場合に使用されます。サーバーは、ユーザーが競合の原因を認識するのに十分な情報を含むペイロードを生成する必要があります(SHOULD)。

この最後のビットに注意してください-409応答のペイロードは、問題の内容に関する情報をコンシューマーに伝達する必要があり、理想的には、競合の解決に役立つリソースにコンシューマーを導くハイパーメディアコントロールが含まれています。

私の解決策は、409が原因で何かが失敗したときにクライアントに通知を表示するAJAX呼び出しのいずれかの失敗ハンドラーをラップすることでした-これはすべて問題なく、他の4XXおよび5XXと一緒にうまく機能します同じメカニズムを使用するエラー。

そして私はこれを問題として指摘します。クライアントでの実装では、ステータスコードは問題を定義するのに十分であると想定していました。代わりに、クライアントコードはペイロードを確認し、そこで利用可能な情報を処理する必要があります。

つまり、結局のところ、ドキュメントストアがそれを行う方法

409  Conflict

your proposed change has been declined because ${REASON}.  
The following resolution protocols are available: ${LINKS[@]})

400 Bad Requestを使用した同じアプローチも許容されます。おおまかに」は「リクエストに問題がありました。どのステータスコードが最適であるかわからないので、ここに進みます。詳細については、ペイロードを参照してください。」

私は422を使用します。入力は有効であるため、400は適切なエラーコードではありません

WebDAV仕様には この推奨事項 が含まれています

422(Unprocessable Entity)ステータスコードは、サーバーがリクエストエンティティのコンテンツタイプを理解しているため(415(Unsupported Media Type)ステータスコードが不適切)、リクエストエンティティの構文が正しい(つまり、400(Bad Request )ステータスコードは不適切)ですが、含まれている指示を処理できませんでした。たとえば、XMLリクエストの本文に整形式(つまり、構文的に正しい)が含まれているが、意味的に誤りのあるXML命令が含まれている場合に、このエラー条件が発生することがあります。

私はそれが完全に一致するとは信じていません(ただし、これは400の代替としての疑問を投げかけることに同意します)。私の解釈では、422は「間違ったエンティティを送信した」という意味で、409は「エンティティを間違った時刻に送信した」という意味です。

別の言い方をすると、422は、要求メッセージが単独で考慮される問題を示し、409は、要求メッセージがリソースの現在の状態と競合することを示します。

ベンナダルの422に関する議論 は検討に役立つかもしれません。

20
VoiceOfUnreason

私の経験では、HTTPエラーコードはビジネスエラーを表すには不十分です。ただし、エラーのクラスを表すのに役立ちます。

したがって、私の推奨事項は、エラーのカテゴリにHTTPエラーコードを使用することですが、ビジネスロジックの失敗には特定のエラーを選択し(例:409競合... 200 OKはここでは誤解を招くでしょう)、特定のビジネスエラーを示すデータを応答に含めます。一部のブラウザはカスタムステータステキストを無視するため、これがステータステキストではなく、応答コンテンツの一部であることを確認してください。私が使用したい言語には、メッセージを表すのに便利な共用体型があります。しかし、エラーの場合に文字列定数を定義することもできます。

// error with text response
409 Conflict "safety_lock_engaged"
409 Conflict "customer_not_eligible_for_selected_discount"
// warning with JSON response
202 Accepted { "backorderedProductIds": [ 37, 476 ] }
20
Kasey Speakman

「Bad Request」を使用して、違反したビジネスルールのIDと、応答の本文に関する詳細を含めることができます。

6
noneconnex

一般に、HTTPステータスコードを使用して特定のビジネスロジックエラーを表すことは避けます。これは、それらがすでに世界標準で定義されている意味上の意味を持っているためです。他のシステム、新しい開発者などは、標準の逸脱によって混乱します。

私が最近の同様の研究で見つけたのは、400 Bad Request検証エラーなどの場合。このように、すべてのビジネスロジックエラーに対してoneステータスコードを使用します。

ちなみに、409は、編集中にリソースが変更され、再度保存しようとしたときに使用する必要があります。

5
Ivo Coumans