たとえば、users/9
に対してGETリクエストを実行しましたが、ID#9のユーザーはいません。最良のレスポンスコードはどれですか。
TL; DR:404
を使う
このブログを参照してください 。それはとてもよく説明しています。
204
に関するブログのコメントの要約:
204 No Content
はブラウザのレスポンスコードとしてはそれほど有用ではありません(ただしHTTPの仕様によると、ブラウザは 'ビューを変更しない'というレスポンスコードとして理解する必要があります)。204 No Content
はですが、何かを返さなくても成功を示すことが必要な場合があるajax Webサービスには非常に便利です。 (特にフィードバックが不要なDELETE
やPOST
sのような場合)。したがって、あなたの質問に対する答えはあなたのケースでは404
を使うことです。 204
は特殊な応答コードで、GET
に応答してブラウザに戻ることはよくありません。
204
および404
よりもさらに適切ではない他の応答コード:
200
は正常に取得されたものなら何でもの本体とともに返されるべきです。取得しているエンティティが存在しない場合は適切ではありません。202
は、サーバーがオブジェクトに対して作業を開始したが、オブジェクトがまだ完全に準備されていない場合に使用されます。確かにそうではありません。 GET
リクエストに応答してユーザー9の構築を開始していませんし、開始もしていません。それはあらゆる種類の規則を破ります。400
は、形式が正しくないHTTP要求(たとえば、不正なhttpヘッダー、誤った順序のセグメントなど)に応答して使用されます。これはほぼ確実にあなたが使っているどんなフレームワークによっても扱われるでしょう。あなたが最初からあなた自身のサーバを書いているのでなければ、これに対処する必要はないはずです。 編集: 新しいRFC では、意味的に無効な要求に400を使用できるようになりました。ウィキペディアの HTTPステータスコード の説明は特に役に立ちます。また、www.w3.orgのHTTP/1.1 RFC2616文書に定義 を見ることもできます 。
空のデータでは204または200を優先して404に反対します。
要求は受け取られ、正しく処理されました - それはサーバのアプリケーションコードを引き起こしました、従ってそれは実際にそれがクライアントエラーであると言うことができず、したがってクライアントエラーコードのクラス全体(4xx)は合いません。
さらに重要なことに、404はいくつかの技術的な理由で発生する可能性があります。例えば。アプリケーションがサーバー上で一時的に非アクティブ化またはアンインストールされていること、プロキシ接続の問題など。したがって、クライアントは「空の結果セット」を意味する404と「サービスが見つかりません。後でもう一度やり直してください」を意味する404を区別できません。
これは致命的になることがあります。年次ボーナスが原因であるすべての従業員をリストするあなたの会社の会計サービスを想像してみてください。残念ながら、呼び出されると404が返されます。これは、だれもがボーナスの原因になっていないことを意味するのでしょうか、それともアプリケーションが現在新しい展開のために停止しているのですか?
- >データの品質を気にするアプリケーションでは、404はほとんど不可能です。
また、多くのクライアントフレームワークは、それ以上の質問をすることなく例外を投げることによって404に応答します。これはクライアント開発者にその例外をキャッチし、それを評価し、そしてそれに基づいてそれをエラーとして記録するかどうかを決定することを強制する。監視コンポーネント、またはそれを無視するかどうか。それは私にもきれいには見えません。
204に対する404の唯一の利点は、要求されたリソースが見つからなかった理由に関する情報を含む応答エンティティを返すことができることです。しかし、それが本当に重要な場合は、200 OK応答の使用を検討し、ペイロードデータのエラー応答を考慮してシステムを設計することもできます。あるいは、404応答のペイロードを使用して、構造化情報を呼び出し元に返すこともできます。彼が受け取った場合XMLやJSONではなくhtmlページで解析できるので、呼び出し側の観点からは妥当な「結果が得られない」という応答ではなく、技術的な問題が発生した可能性があります。あるいはHTTPレスポンスヘッダを使うこともできます。
それでも私は空の応答で204または200を好むでしょう。そのようにして、依頼の技術的実行のステータスが依頼の論理結果から切り離されます。 2xxは「技術的な実行は大丈夫です、これは結果です、それを取扱います」という意味です。
ほとんどの場合、空の結果が許容できるかどうかを判断するのはクライアントに委ねられるべきです。正しい技術的実行にもかかわらず404を返すことによって、クライアントは、単にエラーではないエラーであると見なすことを決定するかもしれません。
もう1つの簡単な類推:「結果が見つかりません」と404を返すのは、SQL照会が結果を返さなかった場合にDatabaseConnectionExceptionをスローするのと同じです。それは仕事を終わらせることができますが、有効な結果と間違えられるであろう同じ例外を投げる可能性のある技術的な原因がたくさんあります。
最初は204が理にかなっていると思いましたが、議論の後、404が唯一の真の正しい回答であると思います。次のデータを検討してください。
ユーザー:ジョン、ピーター
METHOD URL STATUS RESPONSE
GET /users 200 [John, Peter]
GET /users/john 200 John
GET /users/kyle 404 Not found
GET /users?name=kyle` 200 []
DELETE /users/john 204 No Content
いくつかの背景:
検索では配列が返され、一致するものはありませんが、内容は次のようになります。空の配列。
404はもちろんリクエストされたサーバーによってサポートされていないURLのために最もよく知られています、しかし行方不明のリソースは実際には同じです。/users/:name
がusers/kyle
と一致していても、ユーザーKyleは使用可能なリソースではないため、404が適用されます。これは検索クエリではなく、動的なURLによる直接参照ですなので404です。
とにかく、私の2セント:)
リソースは存在するが空である可能性があると予想される場合は、物が空であることを示す表現を付けて200 OKを取得するほうが簡単な場合があると私は主張します。
したがって、0個のアイテムを持つコレクションは1個のアイテムを持つコレクションとまったく同じように扱うことができるため、204ではなく{"Items":[]}を持つ200 OKを返すようにします。その中のより多くの項目。
PUTとDELETEには204 No Contentをそのままにしておきますが、実際には有用な表現がない場合もあります。
/ thing/9が実際には存在しない場合は、404が適切です。
以前のプロジェクトでは、404を使用しました。ユーザー9がいない場合は、オブジェクトは見つかりませんでした。したがって、404 Not Foundが適切です。
オブジェクトは存在するがデータがないため、204 No Contentが適切です。私はあなたの場合だと思いますが、オブジェクトはnotが存在します。
w3 の投稿によると、
200 OK
要求は成功しました。応答とともに返される情報は、要求で使用されているメソッドによって異なります。
202承認済み
要求は処理のために受け入れられましたが、処理は完了していません。
204コンテンツがありません
サーバーは要求を実行しましたが、entity-bodyを返す必要はなく、更新されたメタ情報を返したい場合があります。
400不正な要求
不正な構文のため、要求をサーバーで理解できませんでした。クライアントは変更なしにリクエストを繰り返すべきではありません。
401未承認
要求にはユーザー認証が必要です。応答はWWW-Authenticateヘッダフィールドを含まなければならない
404見つかりません
サーバーはRequest-URIに一致するものを見つけられませんでした。その状態が一時的なものか恒久的なものかは示されていない
要約または単純化するために、
2xx:オプションのデータ:整形式のURI:基準はURIの一部ではない:基準がオプションで@RequestBodyと@RequestParamで指定できる場合、2xxになるはずです。例:名前/ステータスによるフィルタリング
4xx:期待されるデータ:整形式ではないURI:基準はURIの一部です:基準が@PathVariableでしか指定できない必須の場合、それは4xxに導くはずです。例:一意のIDによる検索.
つまり、「users/9」は4xx(おそらく404)になりますが、「users?name = superman」は2xx(おそらく204)になるはずです。
質問が2つあります。タイトルに1つ、例に1つです。私はこれが部分的にどの反応が適切であるかについての論争の量をもたらしたと思います。
質問のタイトルは空のデータについて尋ねます。空のデータはまだデータですが、データがないことと同じではありません。したがって、これは結果セット、つまりおそらくリスト/users
からのリストを要求することを示唆しています。リストが空の場合は、まだリストなので204(No Content)が最も適しています。あなたはたった今ユーザーのリストを要求し、そしてそれと共に提供されました、それはただコンテンツを持っていないことが起こります。
代わりに提供された例は、特定のオブジェクト、ユーザー、/users/9
について尋ねます。ユーザー#9が見つからない場合は、ユーザーオブジェクトは返されません。特定のリソース(ユーザーオブジェクト)を要求しましたが、見つからなかったために指定されませんでした。したがって、404が適切です。
これを解決する方法は、条件付きステートメントを追加しなくても予想どおりに応答を使用できる場合は204を使用し、それ以外の場合は404を使用することです。
私の例では、内容があるかどうかをチェックせずに空のリストを繰り返すことができますが、何かを壊したりnullであるかどうかを確認するチェックを追加しない限りnullオブジェクトにユーザーオブジェクトデータを表示できません。
必要に応じてnullオブジェクトパターンを使用してオブジェクトを返すこともできますが、それは別のスレッドに関する議論です。
既存の回答が詳しく述べていないのは、パスパラメータを使用するかクエリパラメータを使用するかによって違いが生じるということです。
/users/9
の場合、そのリソースが見つからなかったため、応答は404
になります。 /users/9
はリソースであり、結果は単項またはエラーです。存在しません。これはではなくモナドです。/users?id=9
の場合、リソース204
は見つかったがデータを返すことができなかったため、応答は/users
になります。リソース/users
が存在し、結果はn進数です。空の場合でも存在します。 id
が一意の場合、これはモナドです。パスパラメータとクエリパラメータのどちらを使用するかは、ユースケースによって異なります。私は、必須、規範的、識別用の引数にはパスパラメータを使い、オプション、非規範的、または属性付きの引数にはクエリパラメータを使います(ページング、照合ロケールおよびものなど)。 REST APIでは、/users/9
ではなく/users?id=9
を使用します。特に、最初の公開sshキーを取得するための/users/9/ssh-keys/0
や3番目の住所を取得するための/users/9/address/2
のような "子レコード"を取得するためです。
私は404を使うのが好きです。
204
はvoid
メソッドのようなものです。 GET
には使用しません。POST
、PUT
、およびDELETE
にのみ使用します。識別子がパスパラメータではなくクエリパラメータであるGET
の場合は例外にします。NoSuchElementException
、ArrayIndexOutOfBoundsException
などのようなものなので、クライアントエラーです。204
を取得することは、コード内で追加の分岐が避けられることを意味します。これはクライアントコードを複雑にし、場合によってはサーバーコードも複雑にします(エンティティ/モデルモナドを使用するかプレーンエンティティ/モデルを使用するかによって、そしてIを強く使用しますモナドのせいであなたは操作が成功したと思い、実際に何か他のものを返さなければならなかったときに200または204を返すという厄介なバグにつながる可能性があります。大事なことを言い忘れましたが:一貫性
GET /users/9
PUT /users/9
とDELETE /users/9
PUT /users/9
およびDELETE /users/9
は、更新または削除が成功した場合には、すでに204
を返す必要があります。それでは、ユーザー9が存在しなかった場合、それらは何を返すべきですか?使用されているHTTPメソッドに応じて、同じ状況が異なるステータスコードとして表示されるのは意味がありません。
その上、規範的なものではなく文化的な理由:204
がGET /users/9
のために使われるならば、プロジェクトで次に起こることは誰かが204
を返すことがn進法のために良いと考えるということです。そしてそれはクライアントコードを複雑にします、なぜなら単に2xx
をチェックしてからボディをデコードする代わりに、クライアントは今204
を特にチェックしなければならず、その場合ボディのデコードをスキップするからです。クライアントは代わりに何をするのでしょうか。空の配列を作成しますか?それでは、どうしてそれをネットワーク上に載せないのですか。クライアントが空の配列を作成した場合、204はバカ圧縮の形式です。クライアントが代わりにnull
を使用すると、まったく異なるワームの缶が開かれます。
Twitterは404を "No data found"のようなカスタムエラーメッセージとともに使用します。
参照: https://developer.Twitter.com/en/docs/basics/response-codes.html
204がより適切です。特にあなたのウェブサイトが安全であることを保証するための警報システムを持っているとき、あなたがある404警報がバックエンドエラーまたは通常の要求で空であるが応答を知らないのでこの場合404は混乱を引き起こすでしょう。
疑問に思った後、404
を使用すべきではないのはなぜですか?
RFC 7231 に基づいて、正しいステータスコードは204
です
上記のアンサーで、1つの小さな誤解に気付きました。
1.-リソースは:/users
2.- /users/8
はリソースではありません。これは、リソース/users
であり、ルートパラメーター8
であり、消費者はそれに気付かず、違いを知らないかもしれませんが、出版者は知っている必要がありますこれ!...彼は消費者に正確な応答を返さなければなりません。期間。
そう:
RFCに基づいて:リソース/users
は見つかったが、パラメーター8
を使用して実行されたロジックは応答として返されるcontent
を見つけられなかったため、404は正しくありません。は:204
ここでの主なポイントは次のとおりです。404
内部ロジックを処理するリソースさえ見つからなかった
204
は次のとおりです。リソースは見つかりましたが、ロジックは実行されましたが、ルートパラメーターで指定された条件を使用してデータが見つからなかったため、何も返せません。申し訳ありませんが、条件を確認して、もう一度電話してください。
200
:わかりました。リソースが見つかりました。ロジックが実行されました(Imが何も返さない場合でも)これを受け取り、自由に使用します。
205
:(GET応答の最良のオプション)リソースを見つけ、ロジックが実行され、コンテンツがあり、それをうまく使います。これをビューで共有する場合はビューを更新して表示してください。
それが役に立てば幸い。
RFC7231によると - page59( https://tools.ietf.org/html/rfc7231#page-59 )404ステータスコードの応答の定義です:
6.5.4。404 Not Found)404(Not Found)ステータスコードは、Originサーバがターゲットリソースの現在の表現を見つけられなかったか、または存在することを開示する意思がないことを示します。この表現の欠如は一時的または恒久的なものであり、オリジンサーバーがおそらく何らかの設定可能な手段を通して、状態が恒久的である可能性が高いことを知っている場合、410(Gone)ステータスコードは404より優先されます。メソッド定義または明示的なキャッシュ制御によって別段の指示がない限り([RFC7234]のセクション4.2.2を参照
そして、疑問を投げかける主なものは、上記の文脈におけるリソースの定義です。同じRFC(7231)によると、リソースの定義は次のとおりです。
リソース:HTTPリクエストのターゲットは「リソース」と呼ばれます。HTTPはリソースの性質を制限するのではなく、リソースと対話するために使用されるインタフェースを定義するだけです。各リソースはUniform Resource Identifierによって識別されます。 [RFC7230]の2.7節に記述されているように、クライアントはHTTP/1.1リクエストメッセージを構築するとき、([RFC7230]の5.3節)で定義されているように、さまざまな形式の1つでターゲットURIを送信する。リクエストの受信時に、サーバはターゲットリソースの有効なリクエストURIを再構築します([RFC7230]の5.5項)HTTPの設計目標の1つは、リクエストのリクエストセマンティクスをベストにすることで可能になるリクエストセマンティクスからリソース識別を分離することです。 methodのセマンティクスとURI自体が暗示するセマンティクスとの間に矛盾がある場合は(4.2.1節で説明されているように)、メソッドのセマンティクスが優先されます。
だから私の言うところでは404ステータスコードは成功したGETリクエストで空の結果で使われるべきではない(例:特定のフィルタに対して結果がないリスト)
どちらも本当に適切ではありません。言われたように - 例えば。 @annebによると、私も、問題の一部はHTTP応答コードを使用してRESTfulサービスに関連するステータスを転送することから生じると考えています。 RESTサービスがそれ自身の処理について言っていることはすべてREST固有のコードによって転送されるべきです。
HTTPサーバーが送信された要求に応答する準備ができているサービスを見つけた場合、HTTP 404で応答するべきではありません。要求を処理するサービス。
しばらくの間、次のURLを仮定しましょう:http://example.com/service/return/test
。
404
が正しいです。ある種類のサービスにこのファイルを正確に配信するように要求し、そのサービスがその名前のものが存在しないことを伝えている場合も同様です。明示的に異なる動作を要求するサービスからの応答がないと、HTTPサーバーは3つのことしか言えません。
503
。200
で、HTTPサーバーが実際に要求を満たすことができます - サービスが後で何を言っても関係ありません。400
または404
は、(「存在するがオフライン」ではなく)そのようなサービスがないことを示し、他には何も見つからなかったことを示します。当面の質問に戻るには:私が最も賢明なアプローチは、以前に述べた以外には一切HTTPレスポンスコードを使用しないことであると思います。サービスが存在し、応答している場合、HTTPコードは200になります。応答には、サービスから返されたステータスが別のヘッダーに含まれている必要があります。
REST:EMPTY
例それはSTHを検索するように求められた場合。その研究は空に戻った。REST:NOT FOUND
。 「IDのような」 - ファイル名またはリソースのIDまたはエントリ番号24など - およびその特定のリソースが見つからなかったこと(通常、1つの特定のリソースが要求され、見つからなかったこと)。REST:INVALID
。(HTTPレスポンスコードと同じ値または表現を持つことがありますが、まったく異なるという事実を示すために、意図的に "REST:"を前に付けました。)
上記のURLに戻り、ケースBを調べてみましょう。ここで、serviceはHTTPサーバーに対して、このリクエスト自体は処理しないでSERVICE
に渡します。 HTTPはSERVICE
によって渡されるものだけを提供し、SERVICE
によって扱われるのでreturn/test
部分については何も知りません。そのサービスが実行されている場合、HTTPは要求を処理するためにとして実際に何か_を見つけたので、200
を返す必要があります。
SERVICE
によって返される(そして、上で述べたように、これは別のヘッダで見たい)ステータスは、実際に期待されるアクションによって異なります。
return/test
が特定のリソースを要求した場合:存在する場合は、REST:FOUND
のステータスで返します。そのリソースが存在しない場合はREST:NOT FOUND
を返します。一度存在すれば戻ってこないことを知っていればREST:GONE
を返し、ハリウッドになったことを知っていればREST:MOVED
を返すようにこれを拡張することができます。return/test
が検索またはフィルタに似た操作と見なされる場合:結果セットが空の場合は、要求された型と空の状態の空のセットをREST:EMPTY
で返します。要求された型とREST:SUCCESS
のステータスの結果の集合return/test
がSERVICE
によって認識される操作ではない場合:それが完全に間違っている場合はREST:ERROR
を返します(例えばretrun/test
のようなタイプミス)、または後で計画されている場合はREST:NOT IMPLEMENTED
.この区別は、2つの異なることを混同するよりもずっときれいです。また、デバッグが容易になり、処理が少し複雑になるだけです。
問題と議論は、結果がHTTPによって提供されるサービスの状態を表すため、またはsthを表すためにHTTP応答コードが使われているという事実から生じます。それはHTTPサーバ自体の範囲にはありません。この矛盾のために、質問に答えることができず、すべての意見は多くの議論の対象となります。
HTTPサーバーではなくサービスによって処理された要求の状態は、HTTP応答コードによって示されるべきではありません(RFC 6919)。 HTTPコードSHOULD(RFC 2119)は、HTTPサーバが自身のスコープから与えることができる情報、すなわちサービスがリクエストを処理するために見つかったかどうかだけを含みます。
代わりに、実際にリクエストを処理しているサービスへのリクエストの状態についてコンシューマに伝えるために、異なる方法を使用する必要があります。私の提案は特定のヘッダを介してそうすることです。理想的には、ヘッダーの名前とその内容の両方が、消費者がこれらの応答を扱うのを容易にする標準に従っています。
410を使わないのはなぜ?要求されたリソースはもう存在せず、クライアントはそのリソースに対して決して要求をしないと予想されます、あなたの場合はusers/9
。
410の詳細についてはこちらを参照してください。 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
クライアントがそれを有効にし、それに応じてロジックを分岐することを可能にする共通のenumで応答コンテンツをエンコードします。 「データが見つかりません」404と「Webリソースが見つかりません」404の違いをクライアントがどのように区別するのかわかりませんか。誰かにユーザーをブラウズさせたくないZ/ 9クライアントに、リクエストは有効だがデータがなかったかのように気にしない戻ってきた。