web-dev-qa-db-ja.com

有効なリクエストのための適切なRESTレスポンスコードは何ですか?空のデータは何ですか?

たとえば、users/9に対してGETリクエストを実行しましたが、ID#9のユーザーはいません。最良のレスポンスコードはどれですか。

  • 200 OK
  • 202承認済み
  • 204コンテンツなし
  • 400不正な要求
  • 404お探しのページが見つかりませんでした
248
IMB

TL; DR:404を使う

このブログを参照してください 。それはとてもよく説明しています。

204に関するブログのコメントの要約:

  1. 204 No Contentはブラウザのレスポンスコードとしてはそれほど有用ではありません(ただしHTTPの仕様によると、ブラウザは 'ビューを変更しない'というレスポンスコードとして理解する必要があります)。
  2. 204 No Contentですが、何かを返さなくても成功を示すことが必要な場合があるajax Webサービスには非常に便利です。 (特にフィードバックが不要なDELETEPOSTsのような場合)。

したがって、あなたの質問に対する答えはあなたのケースでは404を使うことです。 204は特殊な応答コードで、GETに応答してブラウザに戻ることはよくありません。

204および404よりもさらに適切ではない他の応答コード:

  1. 200は正常に取得されたものなら何でもの本体とともに返されるべきです。取得しているエンティティが存在しない場合は適切ではありません。
  2. 202は、サーバーがオブジェクトに対して作業を開始したが、オブジェクトがまだ完全に準備されていない場合に使用されます。確かにそうではありません。 GETリクエストに応答してユーザー9の構築を開始していませんし、開始もしていません。それはあらゆる種類の規則を破ります。
  3. 400は、形式が正しくないHTTP要求(たとえば、不正なhttpヘッダー、誤った順序のセグメントなど)に応答して使用されます。これはほぼ確実にあなたが使っているどんなフレームワークによっても扱われるでしょう。あなたが最初からあなた自身のサーバを書いているのでなければ、これに対処する必要はないはずです。 編集新しいRFC では、意味的に無効な要求に400を使用できるようになりました。

ウィキペディアの HTTPステータスコード の説明は特に役に立ちます。また、www.w3.orgのHTTP/1.1 RFC2616文書に定義 を見ることもできます

200
Crisfole

空のデータでは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をスローするのと同じです。それは仕事を終わらせることができますが、有効な結果と間違えられるであろう同じ例外を投げる可能性のある技術的な原因がたくさんあります。

268
Jens Wurm

最初は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

いくつかの背景:

  1. 検索では配列が返され、一致するものはありませんが、内容は次のようになります。空の配列

  2. 404はもちろんリクエストされたサーバーによってサポートされていないURLのために最もよく知られています、しかし行方不明のリソースは実際には同じです。
    /users/:nameusers/kyleと一致していても、ユーザーKyleは使用可能なリソースではないため、404が適用されます。これは検索クエリではなく、動的なURLによる直接参照ですなので404です。

とにかく、私の2セント:)

24
Justus Romijn

リソースは存在するが空である可能性があると予想される場合は、物が空であることを示す表現を付けて200 OKを取得するほうが簡単な場合があると私は主張します。

したがって、0個のアイテムを持つコレクションは1個のアイテムを持つコレクションとまったく同じように扱うことができるため、204ではなく{"Items":[]}を持つ200 OKを返すようにします。その中のより多くの項目。

PUTとDELETEには204 No Contentをそのままにしておきますが、実際には有用な表現がない場合もあります。

/ thing/9が実際には存在しない場合は、404が適切です。

21
j0057

以前のプロジェクトでは、404を使用しました。ユーザー9がいない場合は、オブジェクトは見つかりませんでした。したがって、404 Not Foundが適切です。

オブジェクトは存在するがデータがないため、204 No Contentが適切です。私はあなたの場合だと思いますが、オブジェクトはnotが存在します。

19
Max

w3 の投稿によると、

200 OK

要求は成功しました。応答とともに返される情報は、要求で使用されているメソッドによって異なります。

202承認済み

要求は処理のために受け入れられましたが、処理は完了していません。

204コンテンツがありません

サーバーは要求を実行しましたが、entity-bodyを返す必要はなく、更新されたメタ情報を返したい場合があります。

400不正な要求

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

401未承認

要求にはユーザー認証が必要です。応答はWWW-Authenticateヘッダフィールドを含まなければならない

404見つかりません

サーバーはRequest-URIに一致するものを見つけられませんでした。その状態が一時的なものか恒久的なものかは示されていない

11
Dev4World

要約または単純化するために、

2xx:オプションのデータ:整形式のURI:基準はURIの一部ではない:基準がオプションで@RequestBodyと@RequestParamで指定できる場合、2xxになるはずです。例:名前/ステータスによるフィルタリング

4xx:期待されるデータ:整形式ではないURI:基準はURIの一部です:基準が@PathVariableでしか指定できない必須の場合、それは4xxに導くはずです。例:一意のIDによる検索.

つまり、「users/9」は4xx(おそらく404)になりますが、「users?name = superman」は2xx(おそらく204)になるはずです。

9
Ashish Singh

質問が2つあります。タイトルに1つ、例に1つです。私はこれが部分的にどの反応が適切であるかについての論争の量をもたらしたと思います。

質問のタイトルは空のデータについて尋ねます。空のデータはまだデータですが、データがないことと同じではありません。したがって、これは結果セット、つまりおそらくリスト/usersからのリストを要求することを示唆しています。リストが空の場合は、まだリストなので204(No Content)が最も適しています。あなたはたった今ユーザーのリストを要求し、そしてそれと共に提供されました、それはただコンテンツを持っていないことが起こります。

代わりに提供された例は、特定のオブジェクト、ユーザー、/users/9について尋ねます。ユーザー#9が見つからない場合は、ユーザーオブジェクトは返されません。特定のリソース(ユーザーオブジェクト)を要求しましたが、見つからなかったために指定されませんでした。したがって、404が適切です。

これを解決する方法は、条件付きステートメントを追加しなくても予想どおりに応答を使用できる場合は204を使用し、それ以外の場合は404を使用することです。

私の例では、内容があるかどうかをチェックせずに空のリストを繰り返すことができますが、何かを壊したりnullであるかどうかを確認するチェックを追加しない限りnullオブジェクトにユーザーオブジェクトデータを表示できません。

必要に応じてnullオブジェクトパターンを使用してオブジェクトを返すこともできますが、それは別のスレッドに関する議論です。

8
Bluebox

既存の回答が詳しく述べていないのは、パスパラメータを使用するかクエリパラメータを使用するかによって違いが生じるということです。

  • パスパラメータの場合、パラメータはリソースパスの一部です。 /users/9の場合、そのリソースが見つからなかったため、応答は404になります。 /users/9はリソースであり、結果は単項またはエラーです。存在しません。これはではなくモナドです。
  • クエリパラメータの場合、パラメータはリソースパスの一部ではありません。 /users?id=9の場合、リソース204は見つかったがデータを返すことができなかったため、応答は/usersになります。リソース/usersが存在し、結果はn進数です。空の場合でも存在します。 idが一意の場合、これはモナドです

パスパラメータとクエリパラメータのどちらを使用するかは、ユースケースによって異なります。私は、必須、規範的、識別用の引数にはパスパラメータを使い、オプション、非規範的、または属性付きの引数にはクエリパラメータを使います(ページング、照合ロケールおよびものなど)。 REST AP​​Iでは、/users/9ではなく/users?id=9を使用します。特に、最初の公開sshキーを取得するための/users/9/ssh-keys/0や3番目の住所を取得するための/users/9/address/2のような "子レコード"を取得するためです。

私は404を使うのが好きです。

  • 単項(1つの結果)とn-ary(n個の結果)のメソッドの呼び出しは、正当な理由がなくても変わるべきではありません。可能であれば、私は同じ応答コードを持つのが好きです。予想される結果の数はもちろん違います。たとえば、本体はオブジェクト(単項)またはオブジェクトの配列(n進)であると想定します。
  • N-aryの場合、私は配列を返します、そして結果がない場合、私は何も返しません(文書がない)、私は空の集合(JSONの空の配列やXMLの空の要素のような空の文書)を返します)つまり、まだ200ですがレコード数はゼロです。この情報を身体の中以外にワイヤーに載せる理由はありません。
  • 204voidメソッドのようなものです。 GETには使用しません。POSTPUT、およびDELETEにのみ使用します。識別子がパスパラメータではなくクエリパラメータであるGETの場合は例外にします。
  • レコードが見つからないのは、クライアントが存在しないIDを使用しているために発生するNoSuchElementExceptionArrayIndexOutOfBoundsExceptionなどのようなものなので、クライアントエラーです。
  • コードの観点からすると、204を取得することは、コード内で追加の分岐が避けられることを意味します。これはクライアントコードを複雑にし、場合によってはサーバーコードも複雑にします(エンティティ/モデルモナドを使用するかプレーンエンティティ/モデルを使用するかによって、そしてIを強く使用しますモナドのせいであなたは操作が成功したと思い、実際に何か他のものを返さなければならなかったときに200または204を返すという厄介なバグにつながる可能性があります。
  • 2xxがサーバーがクライアントが要求したことを実行したことを意味し、4xxがサーバーがクライアントが要求したことを実行しなかったことを意味し、それがクライアントの障害である場合。クライアントが存在しないIDを要求したため、クライアントがIDで要求したレコードをクライアントに渡さないことはクライアントの責任です。

大事なことを言い忘れましたが:一貫性

  • GET /users/9
  • PUT /users/9DELETE /users/9

PUT /users/9およびDELETE /users/9は、更新または削除が成功した場合には、すでに204を返す必要があります。それでは、ユーザー9が存在しなかった場合、それらは何を返すべきですか?使用されているHTTPメソッドに応じて、同じ状況が異なるステータスコードとして表示されるのは意味がありません。

その上、規範的なものではなく文化的な理由:204GET /users/9のために使われるならば、プロジェクトで次に起こることは誰かが204を返すことがn進法のために良いと考えるということです。そしてそれはクライアントコードを複雑にします、なぜなら単に2xxをチェックしてからボディをデコードする代わりに、クライアントは今204を特にチェックしなければならず、その場合ボディのデコードをスキップするからです。クライアントは代わりに何をするのでしょうか。空の配列を作成しますか?それでは、どうしてそれをネットワーク上に載せないのですか。クライアントが空の配列を作成した場合、204はバカ圧縮の形式です。クライアントが代わりにnullを使用すると、まったく異なるワームの缶が開かれます。

4
Christian Hujer

Twitterは404を "No data found"のようなカスタムエラーメッセージとともに使用します。

参照: https://developer.Twitter.com/en/docs/basics/response-codes.html

3
Jay

204がより適切です。特にあなたのウェブサイトが安全であることを保証するための警報システムを持っているとき、あなたがある404警報がバックエンドエラーまたは通常の要求で空であるが応答を知らないのでこの場合404は混乱を引き起こすでしょう。

3
刘武豪

疑問に思った後、404を使用すべきではないのはなぜですか?

RFC 7231 に基づいて、正しいステータスコードは204です

上記のアンサーで、1つの小さな誤解に気付きました。

1.-リソースは:/users

2.- /users/8はリソースではありません。これは、リソース/usersであり、ルートパラメーター8であり、消費者はそれに気付かず、違いを知らないかもしれませんが、出版者は知っている必要がありますこれ!...彼は消費者に正確な応答を返さなければなりません。期間。

そう:

RFCに基づいて:リソース/usersは見つかったが、パラメーター8を使用して実行されたロジックは応答として返されるcontentを見つけられなかったため、404は正しくありません。は:204

ここでの主なポイントは次のとおりです。404内部ロジックを処理するリソースさえ見つからなかった

204は次のとおりです。リソースは見つかりましたが、ロジックは実行されましたが、ルートパラメーターで指定された条件を使用してデータが見つからなかったため、何も返せません。申し訳ありませんが、条件を確認して、もう一度電話してください。

200:わかりました。リソースが見つかりました。ロジックが実行されました(Imが何も返さない場合でも)これを受け取り、自由に使用します。

205:(GET応答の最良のオプション)リソースを見つけ、ロジックが実行され、コンテンツがあり、それをうまく使います。これをビューで共有する場合はビューを更新して表示してください。

それが役に立てば幸い。

3
rodfraga

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リクエストで空の結果で使われるべきではない(例:特定のフィルタに対して結果がないリスト)

2
Filipe Moisés

どちらも本当に適切ではありません。言われたように - 例えば。 @annebによると、私も、問題の一部はHTTP応答コードを使用してRESTfulサービスに関連するステータスを転送することから生じると考えています。 RESTサービスがそれ自身の処理について言っていることはすべてREST固有のコードによって転送されるべきです。

1

HTTPサーバーが送信された要求に応答する準備ができているサービスを見つけた場合、HTTP 404で応答するべきではありません。要求を処理するサービス。

しばらくの間、次のURLを仮定しましょう:http://example.com/service/return/test

  • ケースAは、サーバーが「単にファイルシステム上のファイルを探している」ということです。存在しない場合は404が正しいです。ある種類のサービスにこのファイルを正確に配信するように要求し、そのサービスがその名前のものが存在しないことを伝えている場合も同様です。
  • ケースBでは、サーバーは「実際の」ファイルでは動作しませんが、実際には要求は他のサービスによって処理されます。ある種のテンプレートシステム。ここでは、サーバーはリソースを認識していないため、リソースの存在について主張することはできません(リソースを処理するサービスから通知されない限り)。

明示的に異なる動作を要求するサービスからの応答がないと、HTTPサーバーは3つのことしか言えません。

  • 要求を処理するはずのサービスが実行されていないか応答していない場合は503
  • それ以外の場合は200で、HTTPサーバーが実際に要求を満たすことができます - サービスが後で何を言っても関係ありません。
  • 400または404は、(「存在するがオフライン」ではなく)そのようなサービスがないことを示し、他には何も見つからなかったことを示します。

2

当面の質問に戻るには:私が最も賢明なアプローチは、以前に述べた以外には一切HTTPレスポンスコードを使用しないことであると思います。サービスが存在し、応答している場合、HTTPコードは200になります。応答には、サービスから返されたステータスが別のヘッダーに含まれている必要があります。

  • REST:EMPTY例それはSTHを検索するように求められた場合。その研究は空に戻った。
  • 特にsthを要求された場合はREST:NOT FOUND。 「IDのような」 - ファイル名またはリソースのIDまたはエントリ番号24など - およびその特定のリソースが見つからなかったこと(通常、1つの特定のリソースが要求され、見つからなかったこと)。
  • 送信されたリクエストの一部がサービスによって認識されない場合はREST:INVALID

(HTTPレスポンスコードと同じ値または表現を持つことがありますが、まったく異なるという事実を示すために、意図的に "REST:"を前に付けました。)

3

上記の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/testSERVICEによって認識される操作ではない場合:それが完全に間違っている場合はREST:ERRORを返します(例えばretrun/testのようなタイプミス)、または後で計画されている場合はREST:NOT IMPLEMENTED.

4

この区別は、2つの異なることを混同するよりもずっときれいです。また、デバッグが容易になり、処理が少し複雑になるだけです。

  • HTTP 404が返された場合、サーバーは「私はあなたが何について話しているのかわかりません」と言ってくれます。私の要求のREST部分は本当に大丈夫かもしれませんが、私はすべての間違った場所でpar'Machを探しています。
  • 一方、HTTP 200とREST:ERRは私がサービスを受けたがサービスへのリクエストで何か問題があったことを教えてくれます。
  • HTTP 200とREST:EMPTYから、私は何も間違っていないことを知っています - 正しいサーバー、サーバーがサービスを見つけ、正しい要求をサービスに送った - しかし検索結果は空です。

概要

問題と議論は、結果がHTTPによって提供されるサービスの状態を表すため、またはsthを表すためにHTTP応答コードが使われているという事実から生じます。それはHTTPサーバ自体の範囲にはありません。この矛盾のために、質問に答えることができず、すべての意見は多くの議論の対象となります。

HTTPサーバーではなくサービスによって処理された要求の状態は、HTTP応答コードによって示されるべきではありません(RFC 6919)。 HTTPコードSHOULD(RFC 2119)は、HTTPサーバが自身のスコープから与えることができる情報、すなわちサービスがリクエストを処理するために見つかったかどうかだけを含みます。

代わりに、実際にリクエストを処理しているサービスへのリクエストの状態についてコンシューマに伝えるために、異なる方法を使用する必要があります。私の提案は特定のヘッダを介してそうすることです。理想的には、ヘッダーの名前とその内容の両方が、消費者がこれらの応答を扱うのを容易にする標準に従っています。

2
dariok

410を使わないのはなぜ?要求されたリソースはもう存在せず、クライアントはそのリソースに対して決して要求をしないと予想されます、あなたの場合はusers/9

410の詳細についてはこちらを参照してください。 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

1
Akshat

クライアントがそれを有効にし、それに応じてロジックを分岐することを可能にする共通のenumで応答コンテンツをエンコードします。 「データが見つかりません」404と「Webリソースが見つかりません」404の違いをクライアントがどのように区別するのかわかりませんか。誰かにユーザーをブラウズさせたくないZ/ 9クライアントに、リクエストは有効だがデータがなかったかのように気にしない戻ってきた。

0
ComeIn