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


58

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

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

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

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

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

詳細、

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

組織

/OrgTree/Get

目標

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

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

追加

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

また、私はこれをリンクしました(1つは似ていますが、見つけることができません)

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


明確にしてください:前提条件によってツリーが常に存在する場合、ツリーが存在しないときにアプリケーションはどのようにバラバラになりますか?(404のように見えることに同意します)
アンドレスF。13年

さて、コードはnullをチェックせず、json文字列をオブジェクトとして解析していました。コード内のある場所では、 "is"ロードされたオブジェクトは内部的に見つからないため存在しません。
ロイックフォール-ラクロア

4
アクセスしようとしているリソースのURIを指定すると、より明確になります。/ goals /の場合、200と空のセットを返します。/ goals / {goal_id}にアクセスしようとしている場合、404を返します。/goals/のリクエストに対して404を返した場合、URIは存在しないため、使用しないでください。
imel96

1
どちらの場合でも、問題は保持されます。何を/GoalTree/GetById?versionId=CompletelyInvalidID返す必要がありますか?指定/GoalTree/GetById?versionId=CompletelyInvalidIDされたリソースが文字通り見つからなかったため、成功しませんでした。

2
すばらしい、今議論はあなたの仕事からインターネットに移りました!今では止められない!
カルロスキャンデロス

回答:


80

疑問がある場合は、ドキュメントを参照してください。HTTPステータスコードのW3C定義を確認すると、次のことがわかります。

200 OK-要求は成功しました。応答で返される情報は、要求で使用される方法によって異なります。

404 Not Found-サーバーはRequest-URIに一致するものを見つけられませんでした。

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

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

したがって、この場合、あなたは正しいです。サービスは、特定のことを要求している「特定のこと」を検索していません。

ウィキペディアが一番いいと思う:

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

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

私にはかなり明確に思えます。

リクエスト例について

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

フォーマットについては、あなたは常にその日付に最も近いリビジョンを返すと言いました。オブジェクトを返すことはありませんので、常に返す必要があります200 OK。これが日付範囲を取ることができ、ロジックがその時間枠内ですべてのオブジェクトを返し、200 OK-0結果を返す場合でも、それはリクエストの目的であるため、結果はOKです-その基準を満たすもののセット。

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

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

  • 2xxコード UA に正しいことをしたことを伝え、リクエストは機能しました。将来もこれを続けることができます。
  • 3xxコード UAに、あなたがたぶん働いていたと思われることを伝えますが、そのことは今や他の場所にあります。将来UA はただリダイレクトに行くと考えるかもしれません。
  • 4xxコード UA に何か間違ったことをしたことを伝えます。構築したリクエストは適切ではないので、少なくとも修正を加えずに再試行しないでください。
  • 5xxコード UA にサーバーが何らかの理由で壊れていることを伝えます。しかし、そのクエリは将来的に機能する可能性があるため、再試行しない理由はありません。(ただし、501は例外です。これは400の問題です)。

5xxコードを使用してコメントで言及しましたが、システムは動作しています。機能しないクエリを尋ねられ、UAにそれを伝える必要がありました。どのようにスライスしても、これは4xxの領域です。

エイリアンが私たちの太陽系に質問することを考えてください

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

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

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

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

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

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

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

コンピューター:200 OK。

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

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

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

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

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


4
+1これは、結果を返さないクエリではありません。これは、既知のWebページをブラウザに要求し、見つけられないようなものです。まさに404が何のためにありますか。
アンドレスF.

2
@ imel96では、クエリ文字列がURLの一部であることを忘れています。
ロイックフォール-ラクロア

1
@LegoStormtroopr面白い「エイリアン」の例は、地球が存在しないときに宇宙が無効ではないため機能します。しかし、OPの説明によると、彼のシステムにはツリー含まれている必要があります。ツリーがなければ、システムは機能しません。
アンドレスF。13年

1
@LegoStormtrooprはデータベーステーブルを想像します。テーブルにクエリを実行すると、結果が得られる場合と返されない場合があります。テーブルはリソースであり、行を返すかどうかに関係なく常に存在します。テーブルは識別可能で、名前があります(httpリソースにURIがあるなど)。行はそうではなく、いくつかのパラメーターにのみ一致します。データベースであっても、何にも一致しない更新を行うと、「OK 0行が影響を受けました」というメッセージが表示されます。
imel96

2
@LegoStormtrooprあなたはすでに答えを持っています。/ GoalTree / GetById?versionId = xを再マップする場合、Locationヘッダーを/ GoalTree / Id / xに設定して301を返す必要があります。
imel96

11

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

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

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


1
うーん。意味あり。404はユーザーエラーですが、OPが説明するように、これは実際にはシステムエラーです。ユーザーのリクエストは完全に有効です!「no tree」はエラーなので、200が正しい応答であることに同意しません。
アンドレスF.

@ imel96空の/ステータスコード4xx / 5xxの代わりに、常に有効なエンティティが返されるようにします。私だけの場合は、たとえばwikiのように有効なエンティティを返します。頭痛が少なく、エラーを処理する必要がありません。現状では、ほぼ500に近いと言えます。システムは未定義の状態にあるため、発生しないはずです。OKを返すことは意味がありません。rfcに関する404も意味がありません。何も意味がない場合... 500だけが意味をなします!
ロイックフォール-ラクロア

@Sybiamよく、非常によく定義されたhttpステータスコードを要求しました。この点で、たとえビジネスロジックがエラーだと言っても、httpサーバーとしてのシステムにエラーがあるという意味ではありません。あなたの場合、それはあなたのリクエストを理解し、あなたのクエリを処理しました、そして結果はエンティティではないことがたまたま起こりました。したがって、500を使用することもできません。少なくともオブジェクトに適切なURIを指定し、rfcの方が意味があるかどうかを検討することを検討してください。
imel96

+1 REST APIがある場合(各エンティティには独自のパスがあります)、404を返すことができますが、パスは動詞であり、常に検出されます。
停止ハーミングモニカ

@OrangeDog:/GoalTree/GetById?versionId=12345 、特定のリソース、つまり12345システム内のバージョンID に対応するデータを識別する完全に適切なURI(少なくとも相対的なURI)です。そのようなIDのデータが存在しない場合、404 HTTP応答が完全に適切です。もちろん、応答の本文には、エラーの特定の性質と原因を示す適切な形式の応答(たとえば、JSON、そのようなリソースを要求する一般的なクライアントが期待する場合)を含める必要があります。
イルマリカロネン

7

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

imel96の応答は、4xxファミリのコードは主にユーザー/クライアントエラー用であり、これは1つではないため、404は適切な応答ではないと確信しました。URLは整形式であり、ツリーがそこになければなりません。そうでない場合、システムは一貫性のない状態です!

したがって、これはサーバーエラー、つまり5xxファミリの何かです。おそらく、一般的な500 Internal Server Errorまたは503 Service Unavailable(サービスは "そこにある必要のあるツリーを取得します")。


2
真実ではありません。ユーザーは存在しないものを求めたためエラーになります。

@LegoStormtroopr存在しないものを要求することは、必ずしもエラーではありません。ネットワークリソースを要求し、ネットワークがダウンしている場合、それはネットワークエラーです。
アンドレスF。13年

1
@LegoStormtrooprさらに、ツリー存在する必要あります。OPの説明に従って、システムはそれなしでは機能できません。したがって、このリソースを要求することは有効です。存在しない場合は、システム(またはサーバー)エラーである必要があります。
アンドレスF.

2
@Sybiam 5xxコードのルートに行く場合、503は「503 Service Unavailable-現在、サーバーは一時的な過負荷またはサーバーのメンテナンスのため、リクエストを処理できません。」サーバーは過負荷ではなく、リクエストを見つけられません。さらに、5xxコードは「サーバーが

1
@AndresF。正直に言うと、500コードはおそらく大丈夫です。質問が時間の経過とともにどのように変化したかを考えると、うまくいくでしょう。ほとんどの場合、すべてがうまくいかない場合は、200を返すことに反対しています。

6

私がいることを言うと思います200または404応答コードのいずれかが有効であることができますが、状況を見てどのように応じて、。

問題は、HTTP応答コードがURLに基​​づいてさまざまなリソースを配信できるサーバーのコンテキストで定義されていることです。この文脈では、の意味と完全に曖昧さはありません。前者は「あなたが求めたリソースはここにあります」と言い、後者は「申し訳ありませんが、私はそのようなリソースを持っていません」と言います。200 OK404 Not Found

ただし、状況によっては、HTTPサーバーと要求されている実際のリソース(ツリー)の間に追加のアプリケーション層があります。アプリケーションは、HTTP仕様で適切に対処されていない一種の中間スペースを占有します。

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

特に、この例では、Webサーバーはアプリケーションを問題なく見つけることができますが、アプリケーションは要求されたサブリソース(ツリー)を見つけることができません。ここで、アプリケーションがサーバーの単なる拡張であり、サブアイテム(ツリー)が実際のリソースであると考える場合、404応答が適切です。サーバーは、実際のリソースを見つけるタスクをアプリケーションに委任しているだけです。 、これは失敗しました。

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

これらの視点は両方とも理にかなっています。 ほとんどの場合、少なくとも通常のWebブラウザーを使用してHTTP経由で直接アクセスすることを意図したアプリケーションについては、前者の見解を支持します。ユーザーは通常、サーバーとアプリケーションの違いなどの内部詳細を気にしません。必要なデータがそこにあるかどうかに注意してください。

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


いずれにせよ、上記のどのビューを好むかに関係なく、留意すべきいくつかの詳細があります。1つは、多くの場合、(本質的に)空のリソースと存在しないリソースとの間に意味のある区別があるかもしれないということです。

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

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

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

最後に、常にポステルの法則に留意する必要あります。

あなたが送るものに保守的であり、あなたが受け取るものに寛大であること。

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


ジレンマは十分に説明しました。
マルセル

ジレンマはありません。この回答は、関連するrfcで定義されているリソースに基づいていません。@LegoStormtrooprの回答の下に私のコメントを参照してください。
imel96

@ imel96:RFC 1630を誤解していると思います:以前のコメントで引用した段落は、完全に読みます:「疑問符( "?"、ASCII 3F 16進数)は、クエリ可能のURI間の境界を区切るために使用されます。オブジェクト、そのオブジェクトに対するクエリを表現するために使われる単語のセットがこのフォームを使用する場合、合成URIは、クエリが元のオブジェクトに適用されることに起因するオブジェクトを表す。(強調鉱山)。このように、クエリ文字列が実際にURIの一部であることは明らかです(クエリ文字列の前の部分は、必然的に、であってもまた ...それだけで有効なURI)
イルマリKaronen

...そしてこの結合されたURIは、クライアントがそのURIをサーバーに送信することで要求する特定のリソースを識別すること。いずれにせよ、RFC 2616(HTTP)は、リソースを「セクション3.2で定義されているように、URIで識別できるネットワークデータオブジェクトまたはサービス」として定義しています。さらに、「HTTPに関する限り、Uniform Resource Identifierは、名前、場所、またはその他の特性を介してリソースを識別する単純にフォーマットされた文字列です」と述べています。
イルマリカロネン

@IlmariKaronenあなたは正しいです。HTTPとRESTを混同しました。?私はあなたが/ GoalTree /取得versionDate = 2000BCのようなURIを持つリソースで何ができるかわからないので、まだかかわらないと思える
imel96

3

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


6
仕様をさらに読むと、「この応答は、主に、ユーザーエージェントのアクティブなドキュメントビューを変更せずにアクションの入力を許可することを目的としています」。そのため、GETリクエストには使用しないでください。
imel96

3

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!

1

それの音から、これは内部使用のためのAPIです。これにより、ブックごと(仕様)であるかどうかに関係なく、最もメリットのあるスキーマを使用することができます。これは、独自のステータスコードを完全に発明することを意味するものではありませんが、有益であれば、ルールを少し「曲げる」ことは問題ありません。

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

また、ツリー存在するはずなので500が適切であるというAndres F.の見解にも同意します。しかし実際には、サーバーエラーを2つのカテゴリに分割するのが好きです。予想外の何かがうまくいかず、私が実際に確認できる何かが間違っていました。これにより、次のステータスコードが生成されます。

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

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

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

同僚に同意できないため投稿しているので、これはちょっとしたキャッチ22です。会社にとって最もメリットのあるシステムを考え出すことができれば、誰がより適切かは関係ありません。

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


0

これに接線方向の突き刺し:最終的に人間が(GUIを介して)APIを使用している場合、エンドユーザーにとって生活を楽にするものなら何でもすることをお勧めします。存在するはずのツリーが存在しない場合は、「ドメインモデルの不整合」エラーです。システムエラーは、メモリが不足した場合、または他のシステム障害が発生した場合です。したがって、5xxを返すことは不適切です。上記の何人かの人々が述べたように、ツリー自体に独自のURIがある場合は4xxが適切かもしれませんが、ここではそうではありません。しかし、404がクライアントに伝えることは次のとおりです。何かを取り戻すまで何度でも試すことができます。200を返した場合、ユーザーまたはユーザーエージェントに十分な診断を返して、ユーザーエージェントが平均値を表示できるようにして、ユーザーが再試行を停止し、サポートに連絡できるようにします。一方、このAPIがシステムのみを対象としている場合、


404はすべて、「そのことはここにはないので、どこにあるのかわかりません」と言っています。3xxと5xxは再試行しても問題ありません。しかし、4xxは、「あなたの現在のクエリは、私があなたの不安を見つけるのに不十分でした。どうぞ行ってください。」と言います。

URL NOT FOUNDとResource NOT FOUNDを区別する可能性が好きです。したがって、サービスエンドポイントは200で稼働していますが、要求されたリソースはNOT FOUND 404(応答本文)です。
レモネード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.