クエリが存在しないオブジェクトを参照していることを示すために、REST APIは500 Internal Server Errorを返す必要がありますか?


39

私は、多数のIoTデバイスのデータを処理するサーバーに常駐するREST APIを使用しています。

私のタスクは、APIを使用してサーバーにクエリを実行し、デバイスに関する特定のパフォーマンス情報を収集することです。

ある例では、利用可能なデバイスとそれに対応する識別子のリストを取得し、その後、それらの識別子(GUID)を使用してサーバーに詳細を照会します。

サーバーは500 Internal Server Error、これらのIDのいずれかでクエリを返しています。私のアプリケーションでは、例外がスローされ、エラーの詳細が表示されません。Postmanで応答をより詳しく調べると、サーバーが以下を含む本文でJSONを返していることがわかります。

errorMessage: "This ID does not exist"

サーバーが最初にIDを提供したという事実は無視してください。これは開発者にとっては別の問題です。

REST API 500 Internal Server Errorは、クエリが存在しないオブジェクトを参照していることを報告するためにを返す必要がありますか?私の考えでは、HTTP応答コードは、APIの内部メカニズムではなく、REST呼び出しのステータスを厳密に参照する必要があります。私が期待する200 OK問題のAPIに独自のだろうエラーと説明を含む応答、と。


REST呼び出しがどのように構成されているかによって、期待に潜在的な違いがあることがわかりました。

これらの例を考慮してください:

  1. http://example.com/restapi/deviceinfo?id=123
  2. http://example.com/restapi/device/123/info

前者の場合、デバイスIDはGET変数として渡されます。404または500は、パス(/restapi/deviceinfo)が見つからないか、サーバーエラーになったことを示します。

2番目の場合、デバイスIDはURLの一部です。私はをよりよく理解しますが、404 Not Foundそれでもパスのどの部分が変数とエンドポイントとして解釈されるかに基づいて議論することができます。


あなたが説明しているこの状態は、成功または失敗とみなされますか?
ロバートハーヴェイ


@RobertHarvey私の期待は、APIがデバイスに関する情報を返すことでした。クエリ自体は成功しているはずですが、デバイスIDが欠落していても、リクエストレベルでエラーが発生することはありません。
-JYelton

18
存在しないIDは404のように聞こえます。500エラーの最も一般的な理由は、ホスティングサーバーが処理するために内部例外を発生させるプログラマーです。それが起こる例外的なケースがある場合もあれば、単に怠programmingなプログラミングである場合もあります。ここで起こっていることを言うのは難しい。
ベリンロリッチ

9
500内部サーバーは「それは私たちのせいで、何かを台無しにしてしまった」という意味であり、このステータスをユーザーに返すことを目指してはなりません。その目的は、基本的にバグを示すことです。ユーザーは、特定のリクエストを行ったときに500を受け取ったと言うことができます。その後、ユーザーはそれを修正できます。
berry120

回答:


96

ここでは、404応答がセマンティックマッチとして最適であると思います。なぜなら、検索しようとしたリソース(クエリに使用されるURIで表される)が見つからなかったからです。本体にエラーペイロードを返すことは妥当ですが、必須ではありません。

RFC 2616によると、404ステータスコードの定義は次のとおりです。

10.4.5 404 Not Found
サーバーは、Request-URIに一致するものを見つけられませんでした。状態が一時的なものか永続的なものかは示されていません。410(Gone)ステータスコードは、サーバーが内部で構成可能なメカニズムを介して、古いリソースが永続的に使用不可であり、転送アドレスがないことを知っている場合に使用する必要があります。このステータスコードは、サーバーが要求が拒否された正確な理由を明らかにしたくない場合、または他の応答が適用できない場合に一般的に使用されます。


6
404は、存在しないIDが取得されるリソースに対応している場合にのみ意味的に一致します。
ロバートハーヴェイ

55
@ThomasOwens結果を返さないクエリは、200のステータスと空の結果の配列を返します。404は、実際には存在しない特定のオブジェクトIDを指定した場合にのみ返されます。
ショーンバートン

11
@ThomasOwens:呼び出し元の観点から、エンドポイントはそう/questionsではありません/questions/368213。そのエンドポイントはシナリオに存在しません。このように考えてください。/foo/barでGETを実行し、バーがない場合、/ fooが存在する場合と存在しない場合で応答が異なるのはなぜですか?
ブライアンオークリー

17
確かに、サーバーエラーではないため、5xxを送信しません。これはクライアントエラーです。クライアントが何か持っていないものを要求したため、4xx、具体的には404を送信します
。– bdsl

7
@ThomasOwens:How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?-400の悪いリクエスト。
ロバートハーヴェイ

34

あなたの例を使用します。

http://example.com/restapi/deviceinfo?id=123

エンドポイントがjson 配列を返す場合、最良の選択は200 OK、結果が見つからなかった場合に空の配列を使用することです。

エンドポイントが単一の結果を返すように設計されている場合、私の選択はになります404 NOT FOUND。なぜなら、私にとってこの種のエンドポイントの正しい構文は次のとおりだからhttp://example.com/restapi/deviceinfo/123です。通常、リクエストパラメータは、フィルタリングとエンドポイントが配列を返す場合にのみ使用します。

http://example.com/restapi/device/123/info

この質問はすでにここで答えられたと思います404 NOT FOUNDリソース123が見つからなかったため、POSTまたはGETの方が適切な選択のようです。

どちらの場合も、リクエストが完了しなかった理由を説明する必要性がわかりません。リクエスト情報とHTTPコードはすでにその理由を説明しています。


2
存在しないIDと不正なURLをどのように区別しますか?
ロバートハーヴェイ

2
@luizfzs、あなたもそれにできる、私はそれで問題を見ることができません。私が開発した一部のAPIでは、応答の本文なしで、成功したPUTまたはDELETE(ここで説明します)で204を使用することを好みます。
デリック

10
そのレベルで、存在しないIDと不正なURLを区別する必要があるのはなぜですか?どちらの方法でも、HTTPに関する限り、有効なリクエストを作成しています。サーバーは...まあ... あなたがアドレス指定しているリソースを見つけることができません。不正なURLは不正なリクエストではありません。それは間違ったものに対する整形式のリクエストです
cHao

6
@cHao開発者として、アイテムが存在しないためにアプリが失敗するかどうか、または誤ってapp.company.cxm / tst /ではなくapp.company.cxm / test /にアプリを向けたかどうかを知りたい
パトリックM

7
@PatrickM:開発者として、エラー応答にはメッセージ本文も含まれることがあります。あなたが本当にそれを望むなら、それは説明的なエラー情報が行くところです。太った指に執着しているという理由だけでセマンティクスを破らないでください。HTTPレベルでは、/itms/1234またはのように混乱したかどうかは関係ありません/items/12234
cHao

27

HTTP 404 サーバーはクライアントが要求しているリソースを理解しているが、そのリソースを持っていないため、正しい。

「REST API」で作業しているということが重要です。APIは、関数を実行するのではなく、REpresentational State Transferを実行するように動作する必要があります。(もちろん、「REST」という用語はより広い意味を持つようになりましたが、ここでもその意味をそのまま使用して効果を発揮できます。)クライアントはURLで記述されたリソースの状態を要求しましたhttp://example.com/restapi/device/123/info。クエリ文字列(/deviceinfo?id=123)は状況を変えません。サーバーは、デバイス123の状態の転送を要求していることを認識していますが、それを既知のリソースとして認識しません。したがってHTTP 404

ここで説明する他の可能な応答には、特定の意味もあります。

  • HTTP 200-私たちはあなたのために状態を得ました。応答本文にあります。
  • HTTP 204-私たちはあなたのために状態を得ました。空白です。
  • HTTP 400-どのリソースについて質問しているのかわかりません。URLを修正してください。
  • HTTP 500-故障しました。あなたのせいではありません。

RFC 2616 Secを参照してください。必要に応じて10。


これについてあなたの意見に同意します。サーバーが404を返していた場合は、サーバーが実行していること(500)よりも意味があります。ありがとうございました。
JYelton

11

5xxエラーは通常、サーバーでエラーが発生し、リクエストを完了できないことを示すために使用されます。サーバーが要求を受け取り、それを正常に解析してから作業を行う場合、5xxエラーは返されません。

クエリで結果が得られない場合に返されるものに何らかの規則があるかどうかはわかりません。あなたが説明するもの(メッセージを含む本文を持つ200)と、結果が見つからなかったことを示す404の両方を見てきました。200はおそらく最も意味があります-要求は正常に完了し、クライアントの要求またはサーバーが要求を処理している間に問題はありませんでした。ボディはクライアントにメッセージを配信できます。


私はあなたの例(http://example.com/restapi/deviceinfo?id=123http://example.com/restapi/device/123/info)の両方を同じように扱います- 123はパラメーターです。どちらの場合も、ID 123のデバイスのデバイス情報を取得するリクエストを構成するさまざまな方法です。

まず、承認と認証を検討します。ユーザーに適切なアクセス許可がない場合、403または401を適切に返します。「無許可」と呼ばれていますが、私の理解では、401は認証に関するものであり、403は無許可または許可が拒否されるものです。ただし、すべての認証および承認エラーについて403だけを使用したい場合は、ここではあまり気にしません。

次に、IDを処理します。あなたの例に基づいて、それは数値IDのように見えます。数値以外の値が指定された場合、400を返します。パラメーターが有効なデバイス識別子である可能性がある場合、処理を続行します。他の引数がある場合は、ここでもチェックされます。応答本文には、リクエストが不正だった理由に関する適切な情報が含まれていると予想されます。

すべてのパラメーターが有効である場合、要求の処理を開始します。システムまたは依存関係(データベース、サードパーティサービス、別の内部サービス)が利用できない場合、5xxコードを返します-503は特定ですが、500も許容されます。どちらの場合でも、追加の詳細を含む本文を返します。外部依存関係が408リクエストタイムアウトを報告する場合、それを食べてクライアントに500を返し、システムへのリクエストがタイムアウトした場合にのみクライアントが408を受信できるようにすることを考慮してください。システムがリクエストを完了できる場合、200と適切なボディを返します。

204は場合によっては便利ですが、応答本文を送信できなくなります。特にAPI設定では、ロギングまたはレポートメカニズムに入力できる情報を含む応答本文を送信することは、ほとんどの場合に行う正しい判断のようです。

404が返されるのは、サーバーに/deviceinfoエンドポイントまたはエンドポイントがない場合のみ/device/:id/infoです。

見つからないIDは、見つからないリソースと同じであるとは考えません。リソースは、特定のデバイスのデバイス情報です(例では)。404を返すということは、リソース(デバイス情報)が存在しないことを意味します。適切なボディを持つ200は、システムが実際にデバイス情報を提供できることを意味します。指定されたIDのデバイスがある場合とない場合があります。


1
@RobertHarveyはい。エラーはありませんでした。サーバーがGUIDを生成してクライアントに送信したからといって、別の操作でGUIDが削除されたわけではありません。要求/応答は成功しました。要求によって表されるコマンドまたはクエリはデータを返しませんでした。私にとって、それは失敗ではありません。それ例外かもしれないが、私はそれが5xxの価値があると確信していません。
トーマスオーエンズ

2
クエリしているこのAPIを設計している場合、ボディに200を返し、その後にの効果を持つ何かを含めdevice: 123; status: not found;ます。その後、クエリが機能し、APIが有用な情報を教えてくれることを知っています
-JYelton

7
@Blrflこれは、多くのWebサイトの500ページの言葉遣いによって裏付けられています(「実証済み」ではありません)。おそらく宇宙線の場合を除いて、適切に機能しているサーバー 500を送信しません。
mbrig

6
Httpには「エンドポイント」という概念がなく、変数とURLの残りの部分との間に関連性のある区別がないため、どちらも残りません。正規表現で一致し、数千のURLを1つのコントローラー関数にルーティングするルーティングシステムがありますが、これは実装の詳細であり、APIの基本的な部分ではありません。getでの200応答は、要求されたリソースが取得されている場合のみです。この場合、クライアントは存在しないリソースの表現を必要とするため、404が正しい応答です。
bdsl

8
適切に機能するシステムは500応答を送信しません。適切に機能するサーバーは500を送信する場合があります。これは、それが大規模システムの一部であり、その大規模システムの内部エラー、たとえばデータベースがダウンしている、またはWebサービスに依存するその他のエラーが無意味な結果を返しているためです。
bdsl

5

500シリーズのHTTPエラーは、サーバーの誤動作を示します。501 Not Implementedおよびを除いて、505 HTTP Version Not Supportedこれらのエラーコードを使用すると、後で要求を再試行すると成功する可能性があります(ただし、503 Service Unavailable明示的にのみ記述されています)。理想的には、サーバーはこれらのコードのいずれかを生成すべきではありませんが、バグのないソフトウェアを記述できず、サーバーに無限のリソースをプロビジョニングできないため、必要になることがあります。

「オブジェクトが存在しない」という結果の404 Not Found場合、おそらく(リクエストが名前によるオブジェクトに対するものである場合)、または200 Success空の結果本文(属性によるオブジェクトの検索時)のいずれかを返す必要があります。 204 No Content魅力的に見えますが、応答ボディの欠如が期待される結果である場合にのみ使用します。


1

APIのクライアントとして、これらの呼び出しのいずれかを行う場合:

  1. http://example.com/restapi/deviceinfo?id=123
  2. http://example.com/restapi/device/123/info

私は、DeviceInfoオブジェクト(または表現)を返すことを期待しています(とにかく、それが正式な型であろうと、文書化された「アヒル型」規約に準拠するものであろうと、特定の型です)。私が欲しい200のステータスが、私は実際に1つを得た、と私は先に行くと、それを使用できることを意味します。

REST APIの場合、400および500のステータスコードは例外のようなものだと思います。これらを使用して、受け取った要求に対して「通常の」応答を返せないことを示すため、クライアントは取得する予定の情報を処理するのではなく、特別なことをする必要があります。

これは、APIコンシューマーとして、応答を取得したり例外をスローしたりする、ある種の確認済み呼び出し関数を使用できることを意味します。それは素晴らしいことです; 私の通常のロジックは直線コードであり、ローカルコードで行うのと同じ方法でエラー処理を整理できます。予期しない404は、何もすることなく「リソースが見つかりません」という例外として現れます。オブジェクトである{ errorMessage: "Device 123 not found" }かのように後で処理するときに「属性がありません」というエラーとしてではありませんDeviceInfo

エンドポイントhttp://example.com/restapi/deviceinfo 見つかり、それ見つからid=123ないだけで、本文にエラーメッセージが含まれる200を返すのであれば、C関数とまったく同じ種類のインターフェイスの問題が発生します。正しい結果またはエラーコード、または任意に戻ることによって問題を示すメソッドnull。インターフェースのユーザーとして、通常の返品とは「別の」チャネルでエラーを示す方がはるかに優れています。これは、HTTP 200、404、および500の応答が低レベルの観点からは同じチャネルであっても、ここでも当てはまります。それらは標準化されており、簡単に区別できるため、RESTクライアントフレームワークはこれらのステータスを簡単に切り替えて、自分の言語の適切な構造に変換できます。JSONレイヤーで同じことを行うには(常に200と言いDeviceInfo、エラーメッセージを表示します)、使用するJSONスキーマに関する知識を埋め込む必要があります。

したがって、期待されるタイプの有効な値を返すことができる場合にのみ200を使用します(これは、http://example.com/restapi/search-devices?colour=blue青色のデバイスがない場合に空の配列で200を返すことができる理由です。空の配列は有効な配列であり、すべての青色のデバイスの詳細が必要です」)。できない場合は、最も適切な200以外のステータスコードを使用してください。にもかかわらず、「存在しないデバイス123は、」「私装置123の詳細を与える」への正しい応答である、とのエラーではありません、サーバー、それは彼らが戻って買ってあげることを、クライアントの期待の例外であるDeviceInfoとすべきは、通常の「ここにあなたが求めたもの」応答として伝えられない。


残念ながら、私はこのAPIのクライアントでもあり、変更できません。これは、それがどのように偉大な要約である必要がありますが、動作します。
-JYelton

0

エラー422 Unprocessable Entityを使用して、404 not foundと区別できます。422は、サーバーが要求を理解しているが、適切な応答を提供できないことを意味します。同様の状況でこのコードを使用しています。


4
この記事では、422の使用について詳しく説明します。このエラーコードは、ここで実際に適用できるとは思わない。
ロバートハーベイ

ありがとう、とても便利です!このテーマを深くしなければなりません!
FiNeX

0

エラー500は通常、リクエストがサーバー側プログラムをクラッシュさせたことを示します。企業環境では、これらのエラーは顔の卵として扱われ、回避されています。

エラー4xxは、APIエンドポイント(リソース)が存在しないことをプログラマに通知する必要があります。そのため、適切なエンドポイントに到達すると、それ以降のエラー処理はAPIのプログラマーの責任となり、適切に処理する必要があります。つまり、200応答のエラーメッセージが発生します。


1
「サーバーをクラッシュさせないので、500は使用しないでください」と言っています。
ロバートハーヴェイ

0

w3は、他の応答が適用されない場合に404​​が使用されると述べていますが、これは204(コンテンツなし)応答が適しているのではないでしょうか?要求は処理の観点から有効であり、サーバーは要求を処理し、結果があります。これは成功であり、2xx応答に傾いています。この特定のリクエストにはコンテンツがなかったため、204はクエリに問題はなかったが、何もなかったことをユーザーに伝えます。

また、409(競合)が適切な応答であるという弱いケースを作成することもできます。409はPOSTに最もよく使用されますが、

リソースの現在の状態と競合するため、要求を完了できませんでした。このコードは、ユーザーが競合を解決し、リクエストを再送信できると予想される状況でのみ許可されます。応答の本文には、ユーザーが競合の原因を認識するのに十分な情報を含める必要があります。理想的には、応答エンティティには、ユーザーまたはユーザーエージェントが問題を修正するのに十分な情報が含まれているはずです。ただし、それは不可能な場合があり、必須ではありません。

おそらく、要求されたIDの非存在はここでの競合であり、システムにそのようなIDが存在しないというメッセージを返すことは、競合を認識して修正するのに十分な情報です。


3
いいえ、getsリクエストの204レスポンスは、リクエストされたリソースが見つかった場合にのみ意味を持ち、その表現は正確にゼロ文字の長さです。
bdsl

0

他の答えはそれをカバーしていますが、私は500シリーズのエラーが「私が台無しにした」ことを意味することを指摘したかったです。この場合、「I」はAPIを意味するため、未処理のサーバーエラーなどが発生します。400シリーズのエラーは、「あなたが台無しになった」ことを意味します。APIの呼び出し元が誤ったものを送信しました。


-4

他のユーザーは、あなたが本を読みたければどうするかについて有効な答えを提供しました。

ただし、RESTfulnessを読みすぎており、RESTfulnessに関して絶対にコーシャであることをお勧めします。

RESTは気まぐれなプロトコルです。使用中に本を読みたい場合は、RESTを介して通信しているという特定の知識を持つクライアントとサーバーの両方を強制的に構築するため、本質的に特定の通信プロトコルはusedは抽象化できません。

別のアプローチがあります。RESTfulnessを完全に避け、それを通信プロトコルとしてのみ使用します。これは、通信プロトコルに関する限り、通信の試行は2つの結果しか得られないため、返される必要がある応答は「HTTP 200 OK」および「HTTP 500 Internal Server Error」のみであることを意味します。サーバーに配信されるかどうか。

配信後に発生することは、通信プロトコルのビジネスではありません。そのため、サーバーがリクエストを正常に受信して処理を開始すると、多くのエラーが発生する可能性がありますが、これらはすべてアプリケーション固有のエラーであり、通信プロトコルのビジネスには関係ありません。通信プロトコルが知る限り、完全に成功しているように見える応答のペイロード内で通信する必要があります。

要するに、「HTTP 200 OK」を返すことをお勧めします。レスポンスペイロード(HTTP用語では「レスポンスコンテンツ本文」)には、「IDが見つかりません」などのアプリケーション固有のエラーコードが含まれます。


downvotesから判断すると、私はいくつかの人々の感情を傷つけたに違いないと思います。または多分彼らの体の他の部分。C-:=
マイクナキス

彼らは本当にこれを読むべきです:blogs.dropbox.com/developers/2015/04/…–
マイク・

1
ここは痛くない。あなたは間違っています。リンクした記事でさえ、エラーと成功が同じに見えるほどひどく誤ったステータスコードの使用については言及していません。「趣味について言えば、APIデザインは、クライアントソフトウェアとサーバーソフトウェアの実際の意味に関するものではないことを覚えておくことが重要です。APIの対象者は、APIを消費しようとしている開発者です。開発者は、使い慣れた他のAPIと同じ規則に従うと、APIの学習と理解が容易になります。」
cHao

@cHaoだから、「Dropboxは現在約10個の異なるステータスコード(8個のエラーと2個の成功)を使用していますが、APIの将来のバージョンでその数を減らすことを計画しています」君は。
マイクナキス

あなたがそれから得ているものを意味しませんでした。彼らが何をしているのかを知っていれば、極端な場合、彼らはそれを1つの成功と4つのエラーコード(400、401、404、500)に減らします。
cHao
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.