RESTful APIは、物がないことを表します


18

人が霊獣を選択したかどうかを識別するAPIを想像してください。彼らはゼロまたは1つのスピリット動物しか持つことができません。

現在:

/person/{id}/selectedSpiritAnimal

動物が選択されると、http 200が返され、 {selectedAnimal:mole}

ただし、選択がない場合は、http 404が返されます。

これは、HTTPエラーとして、まだスピリット動物を選択していない有効なドメインの懸念を表しているため、スピリット動物を不幸にします。

さらに、ビジネスとして-erm Sprit-Animal-Hampers-R-us-誰かに選択がないときを知りたいので、それらを促すことができます。

ここでより良い応答は何ですか:

HTTP 200および {selectedAnimal:null}

またはさらに明示的に

HTTP 200および {selectedAnimal:null, spiritAnimalSelected: false}

それとも、404を返す方が良いでしょうか?this image has not yet been uploadedオンラインで画像を表示するときは404によく似ているのでthis person has not selected a spirit animal


この質問は重複として提案されていますが、その質問は、URLが表す変更を許可しないようにアプリケーションが構成されている場合に要求される有効なURLに対処します。

一方、ここでは、リソースが存在しないことが意味のあるリソースをどのように表すかを検討しています。つまり、クライアントがURLを要求することは有効であり、応答は、モノの不在を表すリソースを正常に要求したということです。

だから、これは「ビジネスロジック」ではなく、物の不在が意味を持っている状況です(404がまだ正しいと主張している多くの同僚がいるかもしれません)が、それをどのようにマッピングするのかわかりませんスペック


答えを選ぶのは非常に難しい。ここでの会話と職場で進行中の会話について、何度も考えを変えました。

ここで落ち着いているのは、仕様書には4xxはクライアントが間違っているときだと言われているということです。この例では、クライアントはselectedSpiritAnimal URLからの応答を予期するように指示されているため、エラーはありません。

私の同僚の間のコンセンサスは、これは悪いAPI設計の症状であるということです

おそらく/ person / {id}をリクエストし、その人のリンク関係のセットを返す方が良いでしょう...もし/ selectedSpiritAnimalリンクが与えられていない場合(人に選択がない場合)とにかくそれを呼び出すと、404が理にかなっています。または、クライアントがデータのサブセットを要求しない限り、部分応答を実装し、/ person / {id}がより完全なドキュメントを返すようにすること


5
404を返すことが問題であると考える理由を説明していません。ドメインの観点から、クライアント層によって抽象化された404または200のどちらを受け取ったかはわかりません。
ビンセントサバード

14
または、204のコンテンツなしを返す方が良いでしょうか?
ポールダンブラ

6
私は404と私の心配は、設定の変更を一義化されていると、その紹介がない精神動物と人の悪いURLテンプレート
ポールD'Ambraの

2
@ PaulD'Ambra価値のあることのために、私はノーコンテンツを使用しません。XmlHttpRequestの時代以来、JavascriptでフロントエンドでHTTPコードがそのように処理されるのを見たことはありません。しかし、それは確かに有効です。
ブランドンアーノルド

回答:


24

このシナリオでは、おそらくHTTP 4xxコードは適切な選択ではありません。あなたは、ゼロのスピリット動物を持つことは有効な状態であり、APIルートperson/{id}/selectedSpiritAnimalは人idが持っているか持っていないかを説明すると述べています。

HTTP 4xx応答は、クライアントがリクエストで何か間違ったことをした場合のために予約されています(元の仕様のw3のアーカイブを参照)。しかし、クライアントは、人idが霊獣を飼っているかどうかにかかわらず、有効なリクエストを行っています。

そこで、適切にフォーマットされたJSONボディを応答に使用し、HTTP 2xxコードを使用する2番目のソリューションに傾倒します。

そのようなリクエストをid受け取って、人が存在しないことが判明した場合、4xxコードの方が理にかなっています。


17
「HTTP 4xx応答は、クライアントがリクエストで何か間違ったことをした場合のために予約されています」。仕様に関する信頼できるステートメントを作成するときは、実際のHTTP仕様を参照してください。(a)その上に構築されたフレームワーク、または(b)ランダムなブログ投稿ではありません。
エリックスタイン

5
@EricStein私はそれについて少し怠feelに感じました。批評をありがとう。更新しました。
ブランドンアーノルド

1
ここのRFCリンクは矛盾しているように感じます。一方で4xx部分は言いますcases in which the client seems to have erredが、もう一方で404は直接言いThe server has not found anything matching the Request-URIます。存在しないものを要求すると、クライアントエラーが発生する可能性があります。私は存在しない人と存在しないサブプロップを理解していますが、それは応答メッセージとして示される可能性があります。エンティティは存在しますが、サブプロパティのコンテンツがないため、204も関連しているようです。
shortstuffsushi

1
クライアントは何か間違ったことをしました。存在しない場合は、選択した精霊動物をユーザーに要求しました。それはまさに404の意味です...あなたはそこにない何かを求めてきました。
アンディ

5
私のブラウザがsoftwareengineering.stackexchange.com/questions/unicorn にリクエストを行うと、それは有効なリクエストですが、それでも404が表示されます(「ユニコーン」というIDの質問はたまたまありません)。
user253751

24

リチャードソン成熟度モデルを紹介しましょう。

問題は、2つのリソースを1つとして表現していることです。ハイパーメディアによって示される関係を持つ2つのリソースが実際にあるはずです。関係を記述するためにハイパーメディアを使用することは、Restの輝かしいレベル3です。

あなたの人はURIの下に住み/person/{id}、動物はの下に住むべき/spiritanimal/{id}です。人は、動物へのリンクを使用して、霊獣があることを示す必要があります。

id 123とユニコーンスピリット動物を持つボブと呼ばれる人を想像してみましょう。

GET /person/123

戻ります;

{
  "name": "Bob",
  "links": [
    {
      "rel": "spiritanimal",
      "uri": "/spiritanimals/789"
    }
  ]
}

これで、人123を読んだ人は、自分が霊獣を飼っていることを知り、さらに詳しい情報を得ることができるURIを持っています。

GET /spitiranimal/789

戻るかもしれない

{
  "type": "Unicorn"
}

次に、ID 456を持ち、スピリットアニマルを持たないフレッドという人物を想像してみましょう。

GET /person/456

戻ります;

{
  "name": "Fred",
  "links": [
  ]
}

今、人456を読む誰もが、リンクがないので、彼らが精神動物を持っていないことを知っています。関係がないことを表すためにHTTPステータスコードを使用する必要はありません。


1
APIを変更する機能を考えると、ある程度のHATEOASがおそらく正しいソリューションになるという質問に付け加えただけです。それはその良い例だ
ポールD'Ambraの

1

これは、霊獣を取得するための適切なURLです。したがって、404エラーは不適切です。404は、論理的な問題ではなく、技術的な問題を表すためのものです。

適切な解決策は、http 200と {"selectedAnimal": null}

あなたは持つべき別々の Webメソッド/person/{id}/hasSelectedSpiritAnimalを返します{"isSpiritAnimalSelected": false}。舞台裏では、同じメソッド呼び出しを行う場合としない場合があり、nullの場合はfalseを返すだけですが、消費するコードではなく、決定するのはそれです。

クエリが密接に関連している場合でも、そうすることを強いる理由なしに、クエリを1つのWebメソッドに分離するために結合することを避ける方が良いです。


1
これが適切な解決策であると考える理由を説明してください。返されるデータがないときにデータを返す意味がありません。URLは問題ないので404は意味がないので、204が私にとって最も意味があるようです。
ビンセントサバード

2
@VincentSavardステータスコードは、jsonの応答よりも扱いが難しく、ドメイン情報を伝えるよりも技術的な問題により適しています。
TheCatWhisperer

2
204:本文が空のコンテンツありません。それはすべて明確で自明です。さらに議論する必要はありません。全体として、明確な設計パターンがない場合、SEはそれを選択し、必要に応じて曲げ、ドキュメントを提供する必要があります。204応答で本文を返すことは重要ではありません。
formixian

2
@formixian ... json / httpの代わりにbjson / tcp apiを作成していた場合、この場合は何を返しますか?httpコードに依存することは、apiの結果をそのhttp実装に不必要にバインドするように思えます。
TheCatWhisperer

2
@VincentSavard When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"コンテンツなしはコンテンツなしを意味します。すなわち、「」を返します。これら2つはまったく似ていません。「スピリットアニマルは現在ファイルされていません」は「」とは大きく異なります。
シェーン

1

エンドポイントが表すものは単なる動物ではありません。それは動物またはそれの欠如です。これは、Optional/ Maybe/ Nullable/などで最もよく表される値です。

したがって、正当な値(200 OKなど)は次のようになります。

  • {'animal': <some animal>, 'selected': true}
  • {'animal': null, 'selected': false}

私は想像できるDELETEエンドポイントに適用された場合に、この方法を設定することができます'selected'false、選択された動物設定されていないこと、再び。

もちろん、'selected'ここにキーをドロップすることもできます。わかりやすくするためだけに表示されています。文字列vs nullは区別のために十分です。


0

404を使用する必要があります。

404(Not Found)ステータスコードは、オリジンサーバーがターゲットリソースの現在の表現を見つけられなかったことを示します

RFC7231

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 25 Sep 2017 00:00:00 GMT

this person has not selected a spirit animal

ヒューマンインターフェイスではなくプログラミングインターフェイスを作成しているため、404テキストはオプションです。

できる限り標準プロトコルを好むので、これが好きです。HTTPには存在しないことを表す方法があり、それを使用します。

編集:ユーザーが霊獣を共有するかどうかを選択できる機能を追加し、誰かがそれを共有しなかったとします。200 OK nullまたは200 OK を返し"Unauthorizedますか?または、標準の401 Unauthorized / 403 Forbiddenを使用しますか?これは、そもそも1つを選択しないことに直接似ています。


または、200 OK + JSONを使用する場合は、を返す必要がありnullます。

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

"mole"

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 25 Sep 2017 00:00:00 GMT

null

物事をきれいに保ちます。必要な場合にのみ、さらにラッピングを作成します。


2
ただし、データ見つかりました。データが存在するnull(値がない)ことが起こります。これは、値を保持するスロットが存在しないものを要求するクライアントとは異なります。AttributeError値がたまたまPythonでをスローすることはお勧めしませんNone。これにより、インターフェイスが非実用的になり、操作が不必要に難しくなります。より実用的には、多くのHTTPクライアントAPIが404を言語の標準エラー処理メカニズム(エラーコード、例外、エラータイプ)に変換する可能性があります。つまり、外部エラーを抑制する必要があります。
jpmc26

@Paul Draper仕様を少し上にスクロールすると、HTTP 4xxに関する包括的なステートメントが作成されていることがわかります。opは、霊獣を飼っていないことはAPIが説明すべき有効な状態であると明確に述べています。tools.ietf.org/html/rfc7231#section-6.5
ブランドンアーノルド

では、要求されたリソースが存在しないことを示す(つまり、動物が選択されていない)ことと、クライアントが無効なパスを要求する(つまり/person/{id}/selectedSpritAnimal、タイプミスを観察するSprit)ことをどうやって区別しますか。
sampathsris

1
意図に関係なく、404はリソースが見つからなかったことを厳密に意味します。selectedSpiritAnimalがリソースであり、何も存在しない場合、GETするものはなく、404が適切です。ただし、クライアントが精霊動物が選択されたかどうかを知りたい場合、サーバーは/person/{id}/isSpiritAnimalSelected、クライアントに選択されたかどうかを伝える別のリソースを公開する必要があります。読む前にファイルが存在するかどうかをテストするのと同じ古典的な例のようです。ファイルを読み取り、スローされた場合はENOENTエラーを処理するだけです。
aaaaaa

1
@PaulDraperポイントは、リソースが存在するかどうかではありません。ポイントは、HTTP 4xxコードは、呼び出し元がAPIを誤って使用している場合に使用されることを意味します。Opは、/person/{id}/selectedSpiritAnimalたとえ霊獣が存在しなくても使用されることを意図しています。これは、そのような場合に使用される場合、HTTP 4xxが正しくないことを意味します。また、Opは、これが悪いAPIデザインのにおいである可能性があると正しく述べています。
ブランドンアーノルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.