web-dev-qa-db-ja.com

HTTPステータスコードを使用してアプリケーションレベルのイベントを記述すべきか

私が扱ったいくつかのサーバーは、本文に「success:false」のようなものを含め、クライアントが失敗を考慮すべきリクエストに対してHTTP 200を返します。

これは、特に認証に失敗した場合、HTTPコードの適切な実装のようには思えません。私はかなり簡潔に要約されたHTTPエラーコードを読んだことがあります。「4xx」は変更されるまでリクエストを再度作成してはならないことを示し、「5xx」はリクエストが有効であるかどうかはわからないが再試行できることを示していますが、失敗しました。この場合、200:ログインに失敗した、または200:そのファイルが見つからなかった、または200:パラメーターxが欠落しているのは間違いなく間違っているようです。

一方、「4xx」はリクエストの構造的な問題のみを示すべきであるという議論がなされているのを見ることができました。したがって、200を返すのは適切です。クライアントはリクエストを行うことが許可されているため、不正な401 /認証ではなく不正なユーザー/パスワードですが、たまたま間違っています。この引数は、サーバーが要求を処理して決定を下すことができた場合、応答コードは200になるはずであり、詳細情報について本文をチェックするのはクライアントの責任であると要約できます。

基本的に、これは好みの問題のようです。しかし、それは満足のいくものではないので、誰かがこれらのパラダイムのどちらかがより正しい理由がある場合は、知りたいと思います。

56
Kagan Mattson

興味深い質問です。

基本的に、これをOSIレイヤーに類似した用語で物事を分類する正しい方法に減らすことができます。 HTTPは一般にアプリケーションレベルのプロトコルとして定義されており、HTTPは実際には一般的なクライアント/サーバープロトコルです。

ただし、実際には、サーバーはほとんどの場合リレーデバイスであり、クライアントはWebブラウザーであり、コンテンツの解釈とレンダリングを行います。サーバーは、任意のアプリケーションに物事を渡すだけであり、そのアプリケーションは、ブラウザーが任意のスクリプトを送り返します実行する責任があります。 HTTPインタラクション自体(要求/応答フォーム、ステータスコードなど)は、ほとんどの場合、邪魔になることなく、任意のコンテンツを可能な限り効率的に要求、提供、およびレンダリングする方法の問題です。ステータスコードとヘッダーの多くは、実際にこれらの目的のために設計されています。

アプリケーション固有のフローを処理するためにHTTPプロトコルを便乗させようとする場合の問題は、次の2つのオプションのいずれかが残っていることです。1)要求/応答ロジックをHTTPルールのサブセットにする必要があります。または2)特定のルールを再利用する必要がある場合、懸念の分離が曖昧になる傾向があります。これは最初は見た目がすっきりしているように見えますが、プロジェクトの進展に伴って最終的に後悔する設計上の決定の1つだと思います。

したがって、プロトコルの分離について明示することをお勧めします。 HTTPサーバーとWebブラウザーがそれぞれ独自の処理を行い、アプリがits独自の処理を行うようにします。アプリはリクエストを行うことができる必要があり、レスポンスが必要です。そしてリクエストの方法、レスポンスの解釈方法に関するロジックは、HTTPパースペクティブよりも複雑になります。

このアプローチのもう1つの利点は、言及する価値がありますが、一般的に言えば、アプリケーションは(論理的な観点から)基礎となるトランスポートプロトコルに依存してはならないということです。 HTTP自体は過去に変更され、現在はSPDYに続いてHTTP 2が導入されています。アプリをHTTP機能プラグインにすぎないと見なした場合、新しいインフラストラクチャが引き継ぐときにスタックする可能性があります。

38
Yam Marcovic

この質問は少し意見に基づいていますが、どちらの方法でもかまいません。

私の見たところ、200は「ソフトエラー」を処理できます。 APIの構築に関しては、これらのエラーと「ハードエラー」を区別しようとします。

"ソフトエラー"はステータスコード200で提供されますが、エラーの説明とfalseの成功ステータスが含まれます。 「ソフトエラー」は、結果が「期待どおり」の場合にのみ発生し、厳密な意味では成功しません。

「ソフトエラー」は、実装者にとってヒントの詳細であることに注意することが重要です。そのため、人間が読めるエラーメッセージや、ある種のコードなど、エラーに関する詳細情報も提供することが重要です。エンドユーザーにフィードバックを提供します。これらのエラーは、実装者(およびエンドユーザー)に、サーバー側で何が起こったかについての詳細情報を提供します。

たとえば、検索機能を備えたAPIがあるが、検索中に結果が得られないとします。これは誤りではありませんが、定義の厳密な意味ではなく、「成功」でもありません。

JSON形式の例:

{
    "meta" {
        "success": false,
        "message": "Search yielded no results",
        "code": "NORESULTS"
    }
    "data": []
}

"ハードエラー"一方、エラーに対して推奨されるステータスコードが提供されます。ユーザーはログインしていませんか? – 403 /401。不正な入力? –400。サーバーエラー? – 50X。等々。

繰り返しますが、それは少し意見ベースです。すべてのエラーを同等に扱い、すべてを「ハードエラー」にしたい人もいます。検索結果はありませんか?それは404です!コインの反対側では、検索結果はありませんか? –これは予想どおりのエラーではありません。

考慮すべきもう1つの重要な要素は、たとえばアーキテクチャです。 JavaScript XHRリクエストとjQueryまたはAngularJSを使用してAPIを操作する場合。これらの「ハードエラー」は別のコールバックで処理する必要がありますが、「ソフトエラー」は「成功」コールバックで処理できます。何も壊さない、結果はまだ「期待どおり」です。クライアント側のコードは、成功ステータスとコード(またはメッセージ)を確認します。そしてそれをエンドユーザーに印刷します。

24
die maus

APIには2つの側面があります。APIを実装する努力と、すべてのクライアントがAPIを正しく使用する努力です。

クライアントの作成者として、Webサーバーにリクエストを送信すると、エラー(サーバーと正しく通信したことがない)またはステータスコードを含む応答が返されることがあります。エラーを処理する必要があります。良い対応が必要です。予想され、文書化された「悪い」応答を処理する必要があります。他に戻ってきたものは何でも処理する必要があります。

APIを設計するには、クライアントが最も簡単に処理できるものを確認する必要があります。クライアントが整形式のリクエストを送信し、リクエストが要求するとおりに実行できる場合は、200の範囲で回答する必要があります(その範囲の200以外の数が適切な場合もあります)。

クライアントが「...のようなすべてのレコードを提供してください」と尋ね、ゼロがある場合、成功した200とゼロのレコードの配列が完全に適切です。あなたが言及するケース:

「Login failed」は通常401です。「Could n't find file」は404です。「Missing parameter x」はおよそ500です(実際には、サーバーがリクエストに問題があると判明した場合は400、500サーバーが私の要求によって完全に混乱し、何が起こっているのかわからない場合)。これらの場合に200を返しても意味がありません。それは単にクライアントの作成者として、ステータスコードを見るだけではなく、返信についても検討する必要があることを意味します。 「ステータス200、素晴らしい、これがデータです」とは言えません。

特に「パラメータがありません」-これは、私がこれまでに考えたことではありませんhandle。それは私のリクエストが間違っていることを意味します。私のリクエストが正しくない場合、その間違ったリクエストを修正するためのフォールバックはありません。最初に正しいリクエストを送信します。今、私はそれを処理することを余儀なくされています。 200を取得し、「パラメーターがありません」という応答があるかどうかを確認する必要があります。それはひどい。

結局のところ、多くの異なる状況を処理するためのダースコードが2つか2つあり、それらを使用する必要があります。

16
gnasher729