web-dev-qa-db-ja.com

パラメータは構文的に正しいがビジネスルールに違反している場合、HTTP 400(Bad Request)ステータスを返す必要がありますか?

整数をパラメーターとして取るRESTエンドポイントがあるとします。

/makeWaffles?numberOfWaffles=3

この場合、ワッフルの数を負にすることはできないので(0のワッフルを要求することは時間の無駄です)、正の数にしてください。そのため、正の整数を含まないリクエストを拒否したいと思います。また、いくつかの最大整数を超えるリクエストを拒否したいと思います(今のところ、MAX_INTEGERであるとしましょう)。

誰かが正数以外のワッフルを要求した場合、HTTP 400(Bad Request)ステータスを返す必要がありますか?私の最初の考えはイエスです:それは私がリクエストを完了するための有効な番号ではありません。ただし、 RFC はビジネスルールをスローする理由として言及していません。

400(Bad Request)ステータスコードは、クライアントエラーであると認識されている何か(不正なリクエスト構文、無効なリクエストメッセージフレーミング、または不正なリクエストルーティングなど)が原因で、サーバーがリクエストを処理できない、または処理しないことを示します。

ビジネスルールは、これら3つの例のいずれにも該当しません。構文的に正しく、適切にフレーム化されており、不正なリクエストルーティングではありません。

パラメータが構文的には正しいがビジネスルールに違反している場合、HTTP 400(Bad Request)ステータスを返す必要がありますか?または、返すのにより適切なステータスはありますか?

67
Thunderforge

これは素晴らしい質問であり、HTTPリターンコードの履歴コンテキスト(および矛盾するように見える定義)を考えると、依然として非常に関連性があります。この質問への回答の中にも、矛盾する定義があります。これは、時系列的に移動することで明らかにすることができます。

RFC 2616 (1999年6月)

10.4.1 400不正なリクエスト

不正な構文のため、サーバーはリクエストを理解できませんでした。クライアントは変更せずにリクエストを繰り返すべきではありません。

このRFCの時点で、このステータスコードは構文的に無効なリクエストにのみ適用されます。セマンティック検証のステータスコードにギャップがありました。したがって、RFC 4918が登場したとき、新しいコードが生まれました。

RFC 4918 (2007年6月)

11.2 422処理できないエンティティ

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

422 Unprocessable Entityは、4xxステータスコードの元の仕様でのセマンティック検証のギャップを埋めるために作成されました。ただし、別の関連RFCが2014年に登場し、400を一般化して構文に固有ではなくなりました。

RFC 7231 (2014年6月、明示的にRFC 2616を廃止)

6.5.1。 400不正な要求

400(Bad Request)ステータスコードは、クライアントエラーであると認識されている何か(不正なリクエスト構文、無効なリクエストメッセージフレーミング、または不正なリクエストルーティングなど)が原因で、サーバーがリクエストを処理できない、または処理しないことを示します。

422の説明では、400が不適切である理由は、400(RFC 2616現在)が不正な要求構文に対してのみ返されるためです。ただし、RFC 7231以降、厳密な構文エラーの定義は400には適用されなくなりました。

手元の質問に戻ります。422は技術的にはより具体的ですが、このコンテキストでは、APIパラメータのセマンティック検証に400または422が使用されているのがわかります。現時点で422の定義は技術的に古くなっているため、自分のAPIで422を使用することをためらっています(ただし、公式にどこで認識されているかはわかりません)。 422の使用を奨励するFranの回答で参照されている記事は、RFC 7231がHTTP 400を明確にする2年前の2012年に書かれました。どちらかに標準化するようにしてください。

54
Kyle McVay

私が最初の回答を読んだところ、実際には同意しませんでした。少なくとも私の読書では、不正なリクエスト(400)は「何かが根本的に間違っているため、リクエストを処理することさえできない」という意味です。そして私はこれを見つけました post これは422を返す理由になります。

iETFから

422 Unprocessable Entity(WebDAV; RFC 4918)リクエストは整形式でしたが、セマンティックエラーが原因で追跡できませんでした

リクエストは整形式であるため、これはより適切な応答のようですが、検証ルールを通過しません。

44
Fran

いいえ、できません。 HTTPコードは、アプリケーションのHTTPレイヤー用です。ビジネスルールは完全に異なる層であり、アプリケーション固有であるため、独自の「プロトコル」を考え出す必要があります。

黙示録が発生し、HTTPプロトコルからPigeonsを使用するように切り替える必要があるとします。ハトには戻りコードがないため、ビジネスレイヤーを変更してそれに対応する必要があります。しかし、あなたのビジネスは実際にはまったく変わっていないので、ビジネス層を変更する必要はありません。これらの2つのレイヤー(トランスポートとビジネス)の間の密結合を示しています。

質問に戻ります。何をすべきかは、リクエストで何が起こったかを説明する本文を含む「200 OK」を返すことです。仕様は明確にそう言っています:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1

200 OK

リクエストは成功しました。応答で返される情報は、要求で使用されるメソッドによって異なります。たとえば、

[〜#〜] post [〜#〜]アクションの結果を説明または含むエンティティ。

HTTPリクエストは成功しましたか?はい、あります。Webサーバーはその要求をどう処理するかを認識しています(たとえば、アプリケーションのサーバー部分にそれを渡します)。次に、Webサーバーはこの要求をアプリケーションのサーバー部分に渡します。これは、POSTされたデータを受け取り、処理して(ケースではそれらを検証し)、アプリケーションのクライアント部分に(HTTP応答の本文で)通常の応答を返します。 。アプリケーションのサーバー部分からのこの回答は、「すみません、あなたが送信したデータは有効です」または「申し訳ありませんが、送信したデータは無効です」のいずれかになります。そして、答えの意味を理解するのは、アプリケーションのクライアント部分です。

PS:「400 Bad Request」とは、Webサーバーがあなたが何を望んでいるかを理解しなかったことを意味します。これは、アプリケーションのサーバー部分がリクエストを受信しなかったことを意味します。または、少なくともそれが意味することです:-)

[〜#〜] edit [〜#〜]:POSTではなくGETリクエストを実行していることに気づきました。 GETはアプリケーションの状態を変更してはならないため、これは悪い考えです。 GETは単にサーバーからデータを取得することになっています。ただし、リクエストでは実際にアプリケーションの状態を変更しているため、実際にはPOSTを使用する必要があります。

11
GoFree

はい、エンドポイントの暗黙の規約に従わない入力は「クライアントエラーと認識されたもの」であり、400を返します。

これの例外は、ビジネスルールがセキュリティに関連している場合(そして401 Unauthorizedまたは403 Forbidden ましだろう)。または、400を送信すると、何かの存在に関する情報がリークし、次に404 Not Foundの方が適切な場合があります。

8
Telastyn