web-dev-qa-db-ja.com

APIでHTTPステータスコード404を使用する場合

私はプロジェクトに取り組んでおり、約1時間以上、職場の人々と議論した後です。私はスタック交換の人々が言うかもしれないことを知ることにしました。

システムのAPIを作成しています。組織のツリーまたは目標のツリーを返すクエリがあります。

組織のツリーは、ユーザーが存在する組織です。つまり、このツリーは常に存在している必要があります。組織では、目標のツリーが常に存在する必要があります。 (それは議論が始まったところです)。ツリーが存在しない場合、同僚はステータスコード200で応答に答えるのが正しいと判断しました。次に、ツリーがないときにアプリケーションがバラバラになったため、コードの修正を求め始めました。

私は炎と怒りを惜しまないようにします。

ツリーがないときに404エラーを発生させることを提案しました。それは少なくとも何かが間違っていることを私に知らせます。 200を使用する場合、エラーを処理するために、成功コールバックの応答に特別なチェックを追加する必要があります。オブジェクトを受け取ることを期待していますが、何も見つからないため、実際には空の応答を受け取ることがあります。応答を404としてマークするのはまったく公正に思えます。それから戦争が始まり、HTTPステータスコードスキーマを理解できないというメッセージが表示されました。だから私はここにいて、この場合404の何が問題になっているのですか? 「それはfound何もないので、200を返すのは正しい」という引数さえも得ました。ツリーは常に存在しているはずなので、それは間違っていると思います。何も見つからず、何かを期待している場合は、404にする必要があります。

より詳しい情報、

取得したURLを追加するのを忘れました。

組織

/OrgTree/Get

ゴール

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

私の間違い、両方のパラメーターが必要です。日付に解析できるversionDateが提供されている場合、それはクローズリビジョンを返します。過去に何かを入力すると、最初のリビジョンが返されます。 IDが存在しないIDである場合、200の空の応答が返されるのではないかと思います。

追加

また、この問題に対する最良の答えは、組織の作成時にデフォルトのオブジェクトを作成することです。ツリーがないことは有効なケースではなく、未定義の動作と見なす必要があります。両方のツリーなしでアカウントを使用する方法はありません。そのため、それらは常に存在する必要があります。

また、私はこれをリンクしました(似ていますが、見つかりません)

http://viswaug.files.wordpress.com/2008/11/http-headers-status1.png

62

疑わしい場合は ドキュメントを参照 。 HTTPステータスコードのW3C定義を確認すると、次のようになります。

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

404 Not Found-サーバーはRequest-URIに一致するものを何も検出していません。

APIのコンテキストでは、クエリの作成方法とオブジェクトの取得方法に大きく依存します。しかし、私の解釈は常に次のとおりです。

  • 特定のオブジェクトを要求し、それが存在する場合は200コードを返し、存在しない場合は正しい404コードを返します。
  • しかし、クエリに一致するオブジェクトのセットを要求した場合、nullセットは有効な応答であり、200コードで返されます。これの理由は、クエリが有効で、成功し、クエリが何も返さなかったことです。

したがって、この場合正しい、サービスはsearchingではありません「特定のもの」の場合は、特定のものを要求します。そのものが見つからない場合は、それを明確に伝えます。

ウィキペディアはそれを最もよくしていると思います:

200 OK-...実際の応答は、使用される要求メソッドによって異なります。 GETリクエストでは、レスポンスにはリクエストされたリソースに対応するエンティティが含まれます。

404 Not Found-リクエストされたリソースは見つかりませんでしたが、将来再び利用可能になる可能性があります。クライアントによるその後の要求は許可されます。

私にはかなりはっきりしているようです。

リクエスト例について

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

形式については、あなたは常にその日付に最も近いリビジョンを返すと述べました。オブジェクトを返すことはないため、常に200 OKを返す必要があります。これが日付範囲を取ることができ、ロジックが200 OKを返すその時間枠内のすべてのオブジェクトを返すことになっていても-0結果は問題ありません-結果は問題ありません-その基準を満たすもののセット。

ただし、後者は異なります特定のオブジェクト(おそらく一意であり、そのIDを持つ)。この場合に200 OKを返すのは間違っています。要求されたリソースが存在せず、見つからないためです。

ステータスコードの選択について

  • 2xxコードUAにそれは正しいことをしたであることを伝え、要求は機能しました。将来もこれを続けることができます。
  • 3xxコードUAに、以前は機能していたと思われるものを伝えますが、現在は別の場所にあります。将来的に、UAはリダイレクトに行くことを検討するになるかもしれません。
  • 4xxコードUAに通知何か問題がありました、作成したリクエストは適切ではないため、再試行しないでください、少なくともいくつかの変更なし。
  • 5xxコードUAに通知サーバーが何らかの理由で壊れています。ただし、このクエリは将来的に機能する可能性があるため、再試行しない理由はありません。 (501を除いて、これは400号以上のものです).

5xxコードを使用してコメントで言及しましたが、システムは機能しています。機能せず、UAに通信する必要があるクエリが要求されました。どのようにスライスしても、これは4xxテリトリーです。

太陽系に問い合わせるエイリアンを考えてみましょう

エイリアン:コンピューター、人間が生息するすべての惑星を教えてください。

コンピューター:1件の結果が見つかりました。地球

エイリアン:コンピューター、Earthについて教えてください。

コンピューター:地球-ほとんど無害。

エイリアン:コンピュータ、小惑星帯の外の人間が生息するすべての惑星について教えてください。

コンピューター:0件の結果が見つかりました。

エイリアン:コンピューター、地球を破壊してください。

コンピューター:200 OK。

エイリアン:コンピューター、Earthについて教えてください。

コンピューター:404-見つかりません

エイリアン:コンピューター、人間が生息するすべての惑星を教えてください。

コンピューター:0件の結果が見つかりました。

エイリアン:強大なアーケン帝国の勝利!

85
user69037

/ GoalTree/Get *がリソースではなく動詞のように見えるという事実を無視して、常に200を返す必要があります。URI/ GoalTree/Get *は常にアクセス可能なリソースを表し、結果としてツリーがない場合はクライアントエラーではないからです。リクエスト。返されるエンティティがない場合は、空のセットで200を返します。

エンティティがない場合ではなく、リソースが見つからない場合は404を使用します。

別の言い方をすると、オブジェクトに対して404を返したい場合は、オブジェクトに独自のURIを与えます。

12
imel96

これは興味深い質問です。なぜなら、それはすべてシステムの仕様に関するものだからです。

imel96の応答 4xxコードファミリーは主にユーザー/クライアントエラー、これは1つではありません。 URLは整形式であり、ツリーはそこになければなりません。そうでない場合、システムは不整合な状態にあります!

したがって、これはserverエラー、つまり5xxファミリのエラーです。おそらく、一般的な500内部サーバーエラーまたは503サービスが利用できません(サービスは「そこにあるはずのツリーを取得してください」)。

8
Andres F.

状況の見方に応じて、200または404のいずれかの応答コードが有効になる可能性があります

事は HTTP応答コードserverのコンテキストで定義され、さまざまなresourcesURLに基​​づいて。この文脈では、200 OK404 Not Foundの意味は完全に明確です:前者は「ここにあなたが要求したリソースです」と言い、後者は「申し訳ありませんが、そのようなリソースはありません。 「。

ただし、この状況では、HTTPサーバーと要求されている実際のリソース(ツリー)の間に追加のapplicationレイヤーがあります。アプリケーションは、HTTP仕様では十分に対処されていない一種の中間領域を占有します。

Webサーバーから見ると、アプリケーションはリソースのように種類に見えます。これは通常、他のリソースと同様に、URLの(の一部)によって識別されるサーバー上のファイルです(たとえば、静的ファイル)サーバーがサービスを提供する場合があります。一方、それは奇妙な種類のリソースです。応答のコンテンツを動的に決定する実行可能コードで構成され、場合によってはステータスコードでさえも応答するため、ミニサーバーのようにいくつかの方法で動作します。

特に、この例の場合、ウェブサーバーはアプリケーションを問題なく見つけることができますが、アプリケーションは要求されたサブリソース(ツリー)を見つけることができません。ここで、アプリケーションをサーバーの拡張と見なし、サブアイテム(ツリー)を実際のリソースと見なすと、404応答が適切です。サーバーは、実際のリソースを検索するタスクをアプリケーションに委任しましたが、それを行うことができませんでした。

一方、視点がアプリケーションがリソースである場合、Webサーバーは200応答;結局のところ、アプリケーションが見つかり、正しく実行されました。明らかに、この場合、アプリケーションは実際に期待される形式で有効な応答本文を返し、クエリに一致する実際のデータが見つからなかったことを(形式がエンコードする上位レベルのプロトコルを使用して)示す必要があります。

これらの視点はどちらも理にかなっています。 ほとんどの場合、少なくとも通常のWebブラウザでHTTP経由で直接アクセスすることを目的としたアプリケーションの場合、前者のビューを優先する:ユーザーは通常、サーバーとアプリケーションの違いなどの内部の詳細については気にせず、必要なデータがそこにあるかどうかだけを気にします。

ただし、カスタムの高レベルAPIプロトコルを使用して他のコンピュータープログラムと通信するように設計されたアプリケーションの特定のケースでは、低レベルのトランスポート層としてのみHTTPを使用します後者の見解を支持して行われるべき論拠があります:このようなアプリケーションとインターフェースをとるクライアントにとって、彼らが本当に気にしているのはすべて、HTTPレベルでは、アプリケーションに正常に接続できたかどうかを示します。他のすべては、そのような場合、より高いレベルのプロトコルを使用してより自然に通信されることがよくあります。


いずれの場合も、上記のどのビューを優先するかに関係なく、覚えておくべき詳細がいくつかあります。 1つは、多くの場合、(本質的に)emptyリソースとリソースの間に意味のある区別がある場合があることです。存在しない1つ。

HTTPレベルでは、空のリソースは単に200応答コードと空の応答本文で示されますが、存在しないリソースは404応答とリソース本文で示され、リソースがないことを説明します。より高レベルのAPIプロトコルでは、通常、存在しないリソースを適切なプロトコル固有のエラーコード/メッセージを含むエラー応答で示しますが、空の応答はデータ項目のない通常の応答構造です。

(上記の意味でリソースが「空」であるために、リソースが文字通りゼロバイトである必要はないことに注意してください。たとえば、一致するアイテムがない検索結果は、SQLクエリの結果と同様に、広い意味で空としてカウントされます。行または実際のデータを含まないXMLドキュメント。)

また、もちろん、アプリケーションが、要求されたサブリソースが存在するはずであると本当に確信しているが見つからない場合は、3番目の可能な応答コードが存在します:500 Internal Server Error。このような応答は、リソースの存在がアプリケーションの前提条件であり、リソースが存在しないことが必ずしも内部の誤動作を示している場合に意味があります。

最後に、常に留意してください Postelの法則

"送信するものは保守的に、受信するものは寛大に。"

サーバーが特定の状況で200または404応答で応答する必要があるかどうか言い訳をしない youclient実装者として、どちらかの応答を適切に処理するおよび堅牢な相互運用性を最大化する方法で。もちろん、さまざまな状況で「適切な」処理が何を意味するかは議論の余地がありますが、通常、クラッシュやその他の「バラバラ」を含むべきではありません。

6
Ilmari Karonen

URLが存在しないリソースを表す場合は、404 Not Foundを返します

URLが空のリストであるリソースを表す場合、空のリストと200 OKを返します。

例:

{
  total: 0,
  items: []
}

URLが存在していたリソースを表す場合、410 Goneを返します。

レゴストームトルーパーのダイアログについて:

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK. { total: 1, items:[{name:'Earth'}] }

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 200 OK. {name:'Earth', status: 'Mostly Harmless'}

Alien: Computer, please tell me about all planets humans inhabit, outside the asteroid belt. GET /planets?inhabitedBy=humans&distanceFromSun=lots

Computer: 200 OK. {total:0, items:[] }

Alien: Computer, please destroy Earth. DELETE /planets/earth

Computer: 204 No Content. (or 202 Accepted if it takes some time to destroy Earth)

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 410 Gone

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK 0 {total: 0, items:[] }

Alien: Victory for the mighty Irken Empire!
3
Neil McGuigan

204 No Contentはどうですか?リクエストは正常に処理されましたが、何も返さないことを示しています。これはまだ「成功」ですが、ステータスコードのみに基づく結果があるかどうかを確認できます。

3
modernserf

そのサウンドから、これはinternalを使用するためのAPIです。これにより、本(仕様)であるかどうかに関係なく、benefitを最も多く提供するスキーマを使用するエッジが得られます。これは、独自のステータスコードを完全に発明することを意味するものではありませんが、有益であれば、ルールを少し「曲げ」ても問題ありません。

何か問題が発生したことを示すステータスコードを取得する必要があることについて、私はあなたの立場に同意します。結局のところ、これはステータスコードの目的です。また、例外などをスローするライブラリのメリットも得られます。 200以外のステータスコードでは、明示的にチェックする必要はありません(または、これを行う独自のラッパーを作成できます)。

また、ツリーすべきが存在するため、500が適切であるというAndres F.の見解にも同意します。ただし、実際には、サーバーエラーを2つのカテゴリに分けたいと思います。何かunexpectedがうまくいかず、実際に確認できるものが間違っていました。その結果、次のステータスコードが表示されます。

  • 200-すべてが良い
  • 404-間違ったURL
  • 409-問題が発生しました
  • 500-サーバーで予期しないエラーが発生しました

あなたの特定のケースでは、ツリーがサーバー側に存在するかどうかを確認でき、存在しない場合は409を返します。これは予期されたエラーです(発生する可能性があることがわかっているか、確認できるなど)。 。 409の競合は私の個人的な好みにすぎませんが、座ってチームでこれを決定できる限り、5xxも適切です。

このようにコードを分類すると、エラーの種類をより迅速に特定できますが、組織を超えたメリットがあります。多くの場合、Webサイトのエラーでは、クライアントに予期しないエラーが発生しないようにする必要があります。これはセキュリティ上の問題であり、脆弱性を明らかにするため、一般的な500「エラーが発生しました」を返します。完全なエラーをサーバーに記録します。しかし、予想されるエラーが409として発生した場合は、クライアントにエラーを表示しても安全であり、何が起こったのかを暗示する必要はありません。これは私が語ることができる実用的な使用の1つにすぎませんが、可能性はたくさんあります。

同僚に同意できないためにこれを投稿しているので、これは少し難問22ですが、皆さんはセマンティクスについてもっと議論していて、誰が政治的に正しいのかと思われます。会社にとって最もメリットのあるシステムを考え出せるのであれば、誰がより適切であるかは問題ではありません。

一方、これがパブリックAPIである場合は、コミュニティ間での混乱を避けるために、仕様にできる限り近いことがより重要になります。

1
Despertar

404 ==クライアントが、存在しない「個別」/「コンクリート」リソースをポイントしました。これはクライアントエラーです。

200 ==クライアントは、「コンクリート」リソースのセットの構築を要求しました。セットは常に空にすることもできます。したがって、コレクション(クエリ結果)が空の場合でも、クライアントはエラーを発生させていません。

0
Dave

これに接線を突き刺す:人間が最終的に(GUIを介して)APIを使用している場合、エンドユーザーの生活を楽にするために何でもすることをお勧めします。存在するはずのツリーが存在しないことは、「ドメインモデルの不整合」エラーです。システムエラーとは、メモリが不足した場合、またはその他のシステム障害が発生した場合です。したがって、5xxを返すことは不適切です。上記のいくつかの人々が述べたように、ツリー自体が独自のURIを持っている場合は4xxが適切な場合がありますが、ここではそうではありません。しかし、404がクライアントに伝えるのは次のとおりです。何かが返ってくるまで何度でも試すことができます。 200を返した場合、ユーザーまたはユーザーエージェントに十分な診断を返し、ユーザーエージェントがメッセージを表示して、ユーザーが再試行を停止してサポートに連絡するだけで済むようにすることができます。一方、このAPIがシステムのみを対象としている場合、「例外メッセージ」はAPIの一部である必要があります。これにより、HTTPエラーコードの固有の曖昧さに依存する必要がなく、意味のある何かを返すことができます。消費者によって記録され、エスカレーションされます。

0
user90766