検証の失敗または無効な重複のREST HTTPステータスコード


826

RESTベースのAPIを使用してアプリケーションを構築していて、各リクエストのステータスコードを指定するようになりました。

検証に失敗したリクエスト、またはリクエストがデータベースに重複を追加しようとしている場合、どのステータスコードを送信する必要がありますか?

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.htmlを確認しましたが、どれも正しくないようです。

ステータスコードを送信する際の一般的な方法はありますか?




回答:


780

入力検証失敗の場合:400 Bad Request +オプションの説明。これは、本「RESTful Web Services」で提案されています。二重送信の場合:409競合


2014年6月の更新

関連する仕様は、以前はRFC2616でしたが、400(Bad Request)の使用がかなり狭くなりました。

不正な構文のため、サーバーはリクエストを理解できませんでした

したがって、セマンティックエラーには不適切であると主張された可能性があります。もうそうじゃない; 2014年6月以降、関連する標準RFC 7231は以前のRFC2616に取って代わり、400(Bad Request)の使用をより広く

サーバーは、クライアントエラーと認識されていることが原因で要求を処理できない、または処理しません


3
はい、リクエストの本文は構文の一部です。
デーモンは2010

62
悪い要求は間違いなくこの種の問題に対する最も一般的な応答です。他の唯一の選択肢は、422 Unprocessable Entityです。これは実際にはWebDavからのものですが、IANAに登録されているステータスコードを再利用することは完全に有効です。
Darrel Miller

19
それでは、サーバーが解析できない不正なデータと検証エラーをどのように区別するのでしょうか。クライアントはこれら2つの応答をまったく異なる方法で処理します。検証のために、ユーザーにエラーを表示する可能性があります。本当に「不正なデータ」の場合、エラーをログに記録するため、リクエストを生成するメソッドのバグを修正できます。
Josh Noe

18
RFC7231の解釈には同意しsomething perceived to be a client errorませんが、この段落に記載されている例はすべて、論理エラーではなく、HTTPプロトコルの違反であり、構文、フレーミング、ルーティングです。したがって、HTTP仕様で、アプリケーションレベルでの検証の失敗に対して400を許可していないと思います。
Dima Tisnek 2014

2
422-処理できないエンティティを使用しないのはなぜですか?私にはより論理的に
思え

278
  • 検証に失敗しました:403 Forbidden(「サーバーは要求を理解しましたが、実行を拒否しています」)。世論に反して、RFC2616は「403は失敗した認証のみを目的としている」とは述べていませんが、「403:何をしたいのかはわかっていますが、私はしません」と述べています。その状態は、認証が原因である場合とそうでない場合があります。
  • 重複を追加しようとしています:409競合(「リソースの現在の状態と競合しているため、リクエストを完了できませんでした。」)

あなたは間違いなく応答ヘッダーやボディでより詳細な説明を与えるべきです(例えばカスタムヘッダー-でX-Status-Reason: Validation failed)。


17
@deamon:それは仕様ではありません。それはWikipediaです。つまり、「HTTPステータスコードの意味」に関する誰かの意見です。このページには本質的に「これは403でのApacheの意味、これはIISでの403の意味」とあり、公式のRFCを参照している場所はないことに注意してください。「403はApacheが言うことをすべて意味する」と繰り返しているようです。ない。実際のRFCここにある(関連文書ではなく、Apacheの実装ではなく、実装は、ない他人の実装は、「IIS):w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvorは、建物の左

57
「10.4.4 403 Forbiddenサーバーはリクエストを理解しましたが、リクエストの実行を拒否しています。承認は役に立たず、リクエストは繰り返されるべきではありません。リクエストメソッドがHEADではなく、サーバーがリクエストを公開していない理由を公開したい場合が満たされた場合は、エンティティで拒否の理由を説明する必要があります。サーバーがこの情報をクライアントに提供したくない場合は、代わりにステータスコード404(見つかりません)を使用できます。強調はありません( "SHOULD / SHOULD NOT"はRFC 2119キーワードであり、強調ではありません)。これは、RFCではなく、「禁止」の意味です。
Piskvorが

10
私はこの答えが好きですが、小さな問題がまだ1つあります。仕様によると403が返された場合、「リクエストは繰り返されるべきではありません」。ただし、409を返すことは、「ユーザーが競合を解決してリクエストを再送信できると予想される状況でのみ許可されます」。重複の場合、403がより適切であると思います。競合を実際に解決することはできないためです(リソースの以前のインスタンスを削除することを除く)。
pablobm 2011年

2
エラーメッセージ自体は理由フレーズを変更する必要があるため、ヘッダーを送信するのHTTP/1.0 403 Form validation errorsが最もクリーンな方法です。
aleemb 2012

6
IMO、422 "Unprocessable Entity"はもっと理にかなっています。私の推論は、サーバーリクエストの処理を拒否することではなく、サーバーリクエストを処理できないことです。
tybro0103 2013

225

ステータスコード422、 "Unprocessable Entity"をお勧めします

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

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


11
もちろん、これはHTTPステータスコードです。iana.org/assignments/http-status-codesを参照してください。RFC 2616で定義されたものよりもステータスコードがあります
ジュリアンReschke

7
WebDAVはHTTP 拡張です。「Web分散オーサリングおよびバージョン管理(WebDAV)のHTTP拡張機能」したがって、ステータスコード422はhttpステータスコードではなく、httpの拡張のステータスコードです。
デーモンは

16
デーモン、それは意味がありません。HTTPは新しいコードを定義する方法を定義し、それがWebDAVが行っていることです。理由のためにステータスコードレジストリがあります。
Julian Reschke、2010

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

6
スレッドは「期限切れ」になりません。彼らは生き続ける必要がある、またはトップのグーグル検索結果は不正確になり始めます。
James Billingham、2014年

81

200、300、400、500はすべて非常に一般的です。ジェネリックが必要な場合は、400で十分です。

422は、ますます多くのAPIで使用されており、Railsからそのまま使用されています。

APIにどのステータスコードを選択しても、誰かが反対するでしょう。しかし、私は「400 +テキストステータス」が一般的すぎると思うので、422を好みます。また、JSON対応のパーサーを利用していません。対照的に、JSON応答を伴う422は非常に明示的であり、大量のエラー情報を伝えることができます。

JSON応答といえば、この場合のRailsエラー応答を標準化する傾向があります。

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

この形式はフォーム検証に最適です。これは、「エラー報告の豊富さ」の観点からサポートする最も複雑なケースと考えています。エラー構造がこれである場合、エラー報告のすべてのニーズを処理する可能性があります。


2
引数間の相互作用から生じるエラーについてはどうでしょうか。つまり、arg1は有効でarg2あり、有効ですが、特定の値が送信された2つの組み合わせは無効です。
ジョナ

1
考えすぎません。関係を所有しているように見えるものを1つだけ選択してください。
sethcall 2015

または、両方の引数でエラーが発生します。ユーザーとして、競合している各フィールドのエラーを見たいと思います。
2016年

いいね!陽的が陰的よりも優れている
bhathiya-perera

46

200

うーん...(309、400、403、409、415、422)... 成功したHTTPリクエスト失敗したRESTコールの最良のリターンコードは何かを推測、議論、標準化しようとする多くの回答。

HTTPステータスコードとRESTステータスコードを混在させるのは間違っています。

しかし、多くの実装がそれらを混合しているのを見たので、多くの開発者が私に同意しないかもしれません。

HTTP戻りコードは、HTTP Requestそれ自体に関連しています。REST呼び出しは、ハイパーテキスト転送プロトコル要求を使用して行われ、呼び出されたRESTメソッド自体よりも低いレベルで機能します。RESTは概念/アプローチであり、その出力はビジネス/論理結果ですが、HTTP結果コードはトランスポートです。

たとえば、/ users /を呼び出したときに "404 Not found"を返すと混乱を招きます。

  • URIが間違っている(HTTP)
  • ユーザーが見つかりません(REST)

「403 Forbidden / Access Denied」とは、

  • 特別な許可が必要です。ブラウザは、ユーザー/パスワードを尋ねることによってそれを処理できます。(HTTP)
  • サーバーで構成されているアクセス権が間違っています。(HTTP)
  • 認証する必要があります(REST)

また、リストは「500サーバーエラー」(Apache / Nginx HTTPスローエラーまたはRESTのビジネス制約エラー)または他のHTTPエラーなどで続行される場合があります。

コードから、失敗の理由、HTTP(トランスポート)の失敗、またはREST(論理)の失敗の原因を理解するのは困難です。

HTTPリクエストが物理的に正常に実行された場合、レコードが見つかったかどうかに関係なく、常に 200コードを返す必要あります。URIリソースが見つかり、HTTPサーバーによって処理されたためです。はい、空のセットが返される場合があります。HTTP結果として200の空のWebページを受け取ることは可能ですか?

これの代わりに、いくつかのオプションを使用して200 HTTPコードを返すことができます。

  • 何か問題が発生した場合のJSON結果の「エラー」オブジェクト
  • レコードが見つからない場合、空のJSON配列/オブジェクト
  • より良い処理のための以前のオプションと組み合わせたブールの結果/成功フラグ。

また、インターネットプロバイダーによっては、リクエストを傍受して404 HTTPコードを返す場合があります。これは、データが見つからないという意味ではありませんが、トランスポートレベルで何か問題があります。

Wikiから:

2004年7月、英国の通信プロバイダーであるBT GroupはCleanfeedコンテンツブロッキングシステムを展開しました。このシステムは、Internet Watch Foundationによって違法である可能性があると識別されたコンテンツのリクエストに対して404エラーを返します。他のISPは、同じ状況でHTTP 403「禁止」エラーを返します。検閲を隠す手段として偽の404エラーを採用する慣行は、タイとチュニジアでも報告されています。2011年の革命以前は検閲が厳しかったチュニジアでは、人々は偽の404エラーの性質に気づき、「目に見えない検閲者」を表す「Ammar 404」という架空のキャラクターを作成しました。

単純にこのようなもので答えませんか?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

リクエストが論理的に失敗した場合でも、Googleは常にGeocoding APIでステータスコードとして200を返します。https//developers.google.com/maps/documentation/geocoding/intro#StatusCodes

RESTリクエストが失敗した場合でも、FacebookはHTTPリクエストが成功すると常に200を返します。https//developers.facebook.com/docs/graph-api/using-graph-api/error-handling

シンプルで、HTTPステータスコードはHTTPリクエスト用です。REST APIは、あなたのステータスコードを定義します。


3
実際には、RESTにHTTPステータスコードを使用すると、さらに混乱を招きます。1)開発者のツールボックスに4xxが表示され、それを一見しただけでは、サーバーが適切な値を返したかどうか、または要求の処理にまったく失敗したかどうかを判断できません。そして、2)すべてのエラー/例外/キャッチハンドラーは、どのサーバーが応答として返されたかを確認する必要があります(ほとんどの場合、すべてのサービス呼び出しで行う必要があるため、そうではありません)。3)同じペイロードを取得します(タイプ)成功とエラーの両方のパスで複雑なコードや重複したコードにつながる...非常に混乱します。
szczepanpp 2017

9
この答えは、HTTPプロトコルの元のセマンティクスと、アーキテクチャスタイルとしてのREST over HTTPがHTTPを再利用してWebサービスAPIを実装する方法と混同しています。アーキテクチャスタイルとして、RESTは厳密に従う必要がある標準ではなく、推奨されるアプローチです。検証の失敗に200応答を使用することは正しいか間違っているわけではありませんが、リクエストが成功したが、検証の失敗のために実際に失敗したと応答することは、クライアントにとって混乱を招きます。これは、応答の本文内に隠されている重要な詳細です。クライアントが理解するために解析しなければならないセマンティクス。
Kevin Hooke

5
@Marcodor API呼び出しが失敗したが、成功を示す200を返す場合、これはどのようにして良い考えですか?APIの利用者にとっては不明確で混乱を招きます。
Kevin Hooke

3
HTTPエラーとRESTエラーの分離だけでなく、多くの理由で修正してください。REST検証では、多くの場合、より微妙なニュアンスが必要です。たとえば、レコードは受け入れられましたが、重複としてフラグが付けられているか、一意のインデックス違反のために拒否されています。また、一貫した収益モデルが必要です。.NET BadRequest()メソッドには、通常の戻りモデルとは異なる独自の戻りモデルがあります。それは解析するのが悪夢です。@ KevinHooke、REST検証エラーに対してHTTP 200を返すのは、「メッセージを受信しましたが、答えはノーです。理由はここにあります」のようなものです。HTTP 400を返すと、「何を言っているのかわからない」と言います。
Neil Laslett、2018年

5
「グーグルはそれをするので、それは正しいにちがいない」という議論は私にはクレイジーです。グーグルが子供を実装した何かに挑戦するのはOKです。REST 200呼び出しが失敗してHTTP 200が返されると、APIの呼び出し元が4xxになるので混乱し、かなりのJSON / XMLを本文に含めることができます。
Jery​​l Cook、

43

データベース内の複製は409 CONFLICTです。

422 UNPROCESSABLE ENTITY検証エラーに使用することをお勧めします。

ここで4xxコードのより長い説明をします


6

ステータスコード304が変更されていない場合も、重複する要求に対して許容可能な応答を行います。これはIf-None-Match、エンティティタグを使用するヘッダーの処理に似ています。

私の意見では、@ Piskvorの答えは、元の質問の意図であると私が認識しているものに対するより明白な選択ですが、関連性のある代替案もあります。

重複する要求をエラーではなく警告または通知として扱いたい場合は、304Not Modifiedの応答ステータスコードとContent-Location既存のリソースを識別するヘッダーも同様に有効です。リソースの存在を確認することだけが目的の場合、重複したリクエストはエラーではなく確認になります。リクエストは間違っていませんが、単に冗長であり、クライアントは既存のリソースを参照できます。

つまり、要求は良好ですが、リソースはすでに存在しているため、サーバーはそれ以上の処理を実行する必要はありません。


6
304はGET操作がキャッシングを支援するためのものであることを理解しました。
Sinaesthetic 2015年

6

Ember-DataのActiveRecordアダプターは422 UNPROCESSABLE ENTITY、サーバーから返されることを予期しています。したがって、クライアントがEmber.jsで記述されている場合は、422を使用する必要があります。そうしないと、DS.Errorsには返されたエラーが入力されます。もちろん、422をアダプターの他のコード変更できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.