6

クライアントが特定のリソースにアクセスできるかどうかを判断するための REST API のベスト プラクティスを判断しようとしています。2 つの簡単なシナリオ例:

電話帳検索サービス。クライアントは、たとえばアクセスして電話番号を検索します。
GET http://host/directoryEntries/numbers/12345
...12345はディレクトリ内で検索する電話番号です。存在する場合は、電話番号を持つ人の名前や住所などの情報を返します。

動画フォーマット変換サービスです。クライアントは、ビデオを 1 つの形式で送信します。
POST http://host/videos/
...そして、このビデオ用にサーバーによって生成された「ビデオ GUID」を受け取ります。クライアントは次にチェックします。
GET http://host/videos/[GUID]/flv
... 変換されたバージョンが存在する場合、FLV 形式に変換されたビデオを取得します。

上記の両方のケースで、チェック対象のリソースが存在しない場合に何が起こるかについて言及していないことに気付くでしょう。それが私の質問です。クライアントがリソースがここに存在するかどうかを確認するための適切な RESTful な方法は、リソースに対して(またはおそらく) を呼び出すことであり、リソースが存在しない場合は 404 応答を期待する必要があることを他のさまざまな 場所で読みました。404 応答が広く「エラー」と見なされていることを除けば、これで問題ありません。HTTP/1.1 仕様では、ステータス コードの 4xx クラスは、クライアントが「エラーを起こしたと思われる」場合を対象としていると規定されています。ちょっと待って; これらの例では、クライアントは確かに誤りを犯していません。期待している HEADGET404 (または他のもの。このリソースへのアクセスが許可されていない場合は 403) が返される可能性があり、リソースの要求に間違いはありません。404 は「エラー状態」を示すことを意図したものではなく、単に「これは存在しません」という情報です。

また、ブラウザは、HTTP 仕様が示唆するように、404 応答が本物のエラーであるかのように動作します。Google Chrome と Firebug の両方のコンソールは、XHR リクエストによって 404 が受信されるたびに、エラー ハンドラによって処理されたかどうかに関係なく、大きな赤い「404 Not Found」エラー メッセージを Javascript コンソールに吐き出します。無効にする方法。ユーザーにはコンソールが表示されないため、これは問題ではありませんが、開発者として、JS コンソールで 404 (または 403 など) エラーが大量に表示されることは望ましくありません。それらはエラーではなく、私の Javascript コードによって処理されている情報です。ラインノイズです。私が示した 2 番目の例では、クライアントがサーバーをポーリングしている可能性が高いため、これは極端な回線ノイズです。/flvコンパイルには時間がかかる場合があり、クライアントは非 404 になるまで「まだコンパイルされていません」と表示したいためです。JS コンソールに 1 ~ 2 秒ごとに 404 エラーが表示される場合があります。

では、これは REST でリソースの存在を確認するための最善または最も適切な方法でしょうか? JS コンソールの回線ノイズを回避するにはどうすればよいですか? 私の 2 番目の例では、次のように、別の URI をクエリしてコンパイルのステータスを確認することができます。
GET http://host/videos/[GUID]/compileStatus
...しかし、これはRESTの原則に少し違反しているようです。HTTP を完全に使用して HTTP ヘッダーに注意を払うのではなく、独自のプロトコルを作成して、代わりに知りたいことを伝える情報を本文に返し、常に HTTP 200 を返してブラウザーをシャットダウンします。 . これは、SOAP に対する大きな批判でした。SOAP は、HTTP を最大限に活用するのではなく、HTTP を「回避」しようとします。この原則により、なぜ 404 ステータス コードを返す必要があるのでしょうか? 常に 200 を返すことができます - もちろん、200 はリソースのステータス情報が利用可能であることを示しており、ステータス情報は本当に知りたかったことを示しています - リソースが見つからなかったということです。確かに、RESTful な方法は 404 ステータス コードを返すことです。

このメカニズムは、上記の最初の例に適用すると、さらに不自然に見えます。クライアントはおそらく次のようにクエリします:
GET http://host/directoryEntries/numberStatuses/12345
... そしてもちろん 200 を受け取ります。番号12345ステータス情報が存在し、番号がディレクトリに見つからないことを示しています。これは、存在しない可能性がある場合でも、クエリされたすべての番号が「200 OK」になることを意味します。これは良い REST インターフェイスのように思えますか?

何か不足していますか?リソースが RESTful に存在するかどうかを判断するためのより良い方法はありますか、または HTTP を更新して、2xx 以外のステータス コードを必ずしも「エラー」と見なすべきではなく、単なる情報であることを示す必要がありますか? 2xx 以外のステータス応答を常に JS コンソールに「エラー」として出力しないようにブラウザを設定できるようにする必要がありますか?

PS。ここまで読んでくれてありがとう。;-)

4

4 に答える 4

4

リソースが見つからないことを示すために 404 を使用しても問題ありません。「RESTful Web Services」という本からの引用 (ちなみに REST に関する非常に優れた本):

404 は、サーバーがクライアントの URI をリソースにマップできないことを示します。[...] Web サービスは、URI が「無料」であることを示すクライアントへの信号として 404 応答を使用する場合があります。その後、クライアントはその URI に PUT 要求を送信して、新しいリソースを作成できます。404 は、403 または 401 を隠すための嘘である可能性があることに注意してください。リソースが存在する可能性がありますが、サーバーはクライアントにそのことを知らせたくありません。

サービスが要求されたリソースを見つけることができない場合は 404 を使用します。実際にはリソースの存在に関係のないエラーを示すために過度に使用しないでください。また、クライアントはサービスに「クエリ」を実行して、この URI が空いているかどうかを確認できます。

ビデオ ファイルのエンコードなど、長時間実行される操作の実行

HTTP には、同期要求応答モデルがあります。クライアントはサーバーへのインターネット ソケットを開き、要求を行い、サーバーが応答を送信するまでソケットを開いたままにします。[...]

問題は、HTTP 要求にかかると予想される時間内にすべての操作を完了できるわけではないということです。一部の操作には数時間または数日かかります。HTTP リクエストは、そのような非アクティブ状態の後、確実にタイムアウトになります。そうでなかったとしても、サーバーが応答するのを待つだけで何日もソケットを開いたままにしたい人はいますか? このような操作を HTTP 経由で非同期に公開する方法はありませんか?

ありますが、操作を 2 つ以上の同期要求に分割する必要があります。最初のリクエストで操作が生成され、後続のリクエストでクライアントは操作のステータスを知ることができます。シークレットはステータス コード 202 (「Accepted」) です。

POST /videosしたがって、ビデオ エンコーディング タスクを作成することができます。サービスはタスクを受け入れ、202 で応答し、タスクの状態を説明するリソースへのリンクを提供します。

202 Accepted
Location: http://tasks.example.com/video/task45543

クライアントは、この URI をクエリして、タスクのステータスを確認できます。タスクが完了すると、リソースの表現が利用可能になります。

于 2012-04-21T14:53:31.337 に答える
2

リクエストのセマンティクスを変更したと思います。RESTful アーキテクチャでは、リソースを要求しています。したがって、存在しないか見つからないリソースを要求すると、エラーと見なされます。

私が使う:

  • GET http://host/directoryEntries/numbers/12345存在しない場合は404 。

  • 400 は実際には悪い要求です400 Bad Request

おそらく、あなたの場合、代わりに検索することを考えることができます. 検索は、リソースのコレクションに対してクエリ パラメーターを使用して実行されます。

あなたが望むのは GET http://host/directoryEntries/numbers?id=1234 、200を返し、何も存在しない場合は空のリスト、または一致するリストを返すことです。

于 2012-04-21T14:27:50.367 に答える
2

IMOクライアントは、存在しないリソースを要求する際に間違いを犯しました。どちらの例でも、サービスを別の方法で設計できるため、クライアント側でエラーを回避できます。たとえば、ビデオ変換サービスでは、GUID が既に割り当てられているため、videos/id のメッセージ本文に、変換が行われたかどうかを示すフラグを含めることができます。

同様に、電話帳の例では、リソースを検索しています。これは /numbers/?search_number=12345 などで処理できるため、サーバーは一致するリソースのリストを返し、さらにクエリを実行できます。

ブラウザーは HTTP 仕様で動作するように設計されており、エラーを表示することは本物の応答です (非常に役立ちます)。ただし、JavaScript コードはブラウザーとは別のエンティティーとして考える必要があります。つまり、サービスがどのようなものであるかを認識している Javascript REST クライアントと、サービスに関しては馬鹿げたブラウザがあります。

また、理論上、REST はプロトコルから独立しています。HTTP は、たまたま REST が使用される最も一般的なプロトコルです。考えられるもう 1 つの例は、RESTful であるが HTTP に依存しない設計の Android コンテンツ プロバイダーです。

于 2012-04-21T14:28:11.503 に答える
0

リソースが存在しない場合に GET/HEAD リクエストが 404 (Not Found) を返すのを見たことがあります。リソースのステータスを取得しようとしているだけの場合は、リソースの本体を返すべきではないため、ヘッドリクエストで問題ないと思います。このようにして、リソースを取得しようとしているリクエストと、リソースの存在を確認しようとしているリクエストを区別できます。

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

編集:サーバーが404エラーを処理する方法を示すヘッダーを元のリクエストに追加することによる代替ソリューションについて読んだことを覚えています。200 で応答するようなものですが、ボディは空です。

于 2012-04-21T14:07:11.700 に答える