web-dev-qa-db-ja.com

RESTについて:動詞、エラーコード、および認証

私は、PHPベースのWebアプリケーション、データベース、およびCMSのデフォルト関数をAPIでラップする方法を探しています。

私はいくつかの "スケルトン"フレームワークを見回して見つけました。私の質問の答えに加えて、 Tonic 、それはとても軽量なので私が好きなRESTフレームワークがあります。

私はRESTがその単純さのために最も好きで、それに基づいてAPIアーキテクチャを作成したいと思います。私は基本原則に頭を悩ませようとしていますが、それをまだ完全には理解していません。したがって、たくさんの質問があります。

1。私はそれを正しく理解していますか?

「users」というリソースがあるとします。私はそのように多くのURIを設定することができます:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

これはこれまでのところRESTfulアーキテクチャの正しい表現ですか?

2。もっと動詞が必要です

作成、更新、削除は理論的には十分かもしれませんが、実際にはもっとたくさんの動詞が必要になります。が更新リクエストに埋め込まれる可能性があることを私は認識していますが、それらは特定の戻りコードを持つことができる特定のアクションであり、私はそれらを一つのアクションに投げたくないでしょう。

ユーザーの例で思い浮かぶのは以下のとおりです。

activate_login
deactivate_login
change_password
add_credit

rESTful URLアーキテクチャのようなアクションをどのように表現しますか?

私の本能はのようなURLへのGET呼び出しを行うことだろう

/api/users/1/activate_login 

そしてステータスコードが戻ってくることを期待しています。

ただし、これはHTTP動詞を使用するという考えからは逸脱しています。どう思いますか?

3。エラーメッセージとコードを返す方法

RESTの美しさの大部分は、標準のHTTPメソッドの使用に由来しています。エラーが発生した場合は、3xx、4xx、または5xxエラーステータスコードを含むヘッダーを発行します。詳細なエラーの説明については、本文を使用できます(そうですか?)。ここまでは順調ですね。しかし、何が問題なのかを説明するための独自のエラーコードを送信する方法は何でしょうか(例: "データベースに接続できませんでした"、 "データベースログインが間違っています")。 ?メッセージと一緒にそれを体に入れた場合、後でそれを解析しなければなりません。このようなことのための標準的なヘッダはありますか?

4。認証方法

  • RESTの原則に従ったAPIキーベースの認証はどのようなものですか?
  • RESTクライアントを認証するときにセッションを使用することに対して、それがREST原則の露骨な違反であること以外に強い点はありますか。 :)(ここでは冗談で、セッションベースの認証は私の既存のインフラストラクチャでうまくいくでしょう。)
586
Pekka 웃

私はこの質問に数日遅れて気付きました、しかし私は私がいくらかの洞察を加えることができると思います。これがあなたのRESTfulな事業に役立つことを願います。


ポイント1:私はそれを正しく理解していますか?

あなたは正しく理解しました。これはRESTfulアーキテクチャの正しい表現です。あなたは ウィキペディア から次のマトリックスがあなたの名詞と動詞を定義するのに非常に役に立つのを見つけるかもしれません:


CollectionURIを扱う場合:http://example.com/resources/

  • GET:コレクションのメンバーを一覧表示します。ナビゲーションのために、メンバーのURIも含めてください。たとえば、売り出し中のすべての車をリストします。

  • PUT:「コレクション全体を別のコレクションに置き換える」という意味。

  • POST:コレクションによってIDが自動的に割り当てられる新しいエントリをコレクションに作成します。作成されたIDは通常、この操作によって返されるデータの一部として含まれています。

  • DELETE:「コレクション全体を削除する」と定義されている意味。


メンバーURIを扱う場合:http://example.com/resources/7HOU57Y

  • GET:適切なMIMEタイプで表現されたコレクションのアドレス指定されたメンバの表現を取得します。

  • PUT:コレクションのアドレス指定されたメンバーを更新するか、指定されたIDでそれを作成します。

  • POST:アドレス指定されたメンバをそれ自体でコレクションとして扱い、その新しい下位オブジェクトを作成します。

  • DELETE:コレクションのアドレス指定されたメンバーを削除します。


ポイント2:もっと動詞が必要です

一般的に、動詞がもっと必要だと思うとき、それはあなたのリソースが再識別される必要があることを実際に意味するかもしれません。 RESTでは、常にリソースまたはリソースの集まりに対して行動していることを忘れないでください。リソースとして選択したものは、API定義にとって非常に重要です。

ログインの有効化/無効化:あなたが新しいセッションを作成しているなら、あなたはリソースとして "セッション"を考慮したいかもしれません。新しいセッションを作成するには、本文に資格情報を付けてPOSTからhttp://example.com/sessions/にします。期限切れにするには、PUTまたはDELETE(おそらくセッション履歴を保存するかどうかによって異なります)をhttp://example.com/sessions/SESSION_IDに使用します。

パスワード変更:今回はリソースは "the user"です。古いパスワードと新しいパスワードを本文に入れてhttp://example.com/users/USER_IDするにはPUTが必要です。あなたは「ユーザー」リソースに基づいて行動しており、パスワードの変更は単に更新要求です。これはリレーショナルデータベースのUPDATE文と非常によく似ています。

私の本能は/api/users/1/activate_loginのようなURLにGET呼び出しをすることです

これは非常に根本的なREST原則に反します:HTTP動詞の正しい使い方。どんなGETリクエストも決して副作用を残すべきではありません。

たとえば、GETリクエストでデータベースにセッションを作成したり、新しいセッションIDを指定してCookieを返したり、サーバーに残余を残したりしないでください。 GET動詞は、データベースエンジンのSELECT文に似ています。 GET動詞を使用した要求に対する応答は、静的Webページを要求したときと同じように、同じパラメータを使用して要求したときにキャッシュ可能になる必要があります。


Point 3:エラーメッセージとコードを返す方法

エラーカテゴリとして4xxまたは5xx HTTPステータスコードを検討してください。あなたは体のエラーを詳しく説明することができます。

データベースへの接続に失敗しました:/不正なデータベースログイン:通常、これらの種類のエラーには500エラーを使用する必要があります。これはサーバー側のエラーです。クライアントは何も悪いことをしませんでした。 500エラーは通常「再試行可能」と見なされます。すなわち、クライアントは同じ正確な要求を再試行することができ、そしてサーバの問題が解決されるとそれが成功すると期待することができる。クライアントが私たち人間に何らかのコンテキストを提供できるように、本文に詳細を指定します。

他のエラーのカテゴリは4xxファミリで、これは一般にクライアントが何か問題を起こしたことを示します。特に、このカテゴリのエラーは通常、要求をそのまま再試行する必要がないことをクライアントに示します。永続的に失敗し続けるためです。すなわち、クライアントはこの要求を再試行する前に何かを変更する必要があります。たとえば、「リソースが見つかりません」(HTTP 404)または「不正な要求」(HTTP 400)のエラーがこのカテゴリに入ります。


Point 4:認証方法

ポイント1で指摘したように、ユーザーを認証するのではなく、セッションを作成することを検討することをお勧めします。適切なHTTPステータスコード(200:Access Grantedまたは403:Access Denied)とともに、新しい「セッションID」が返されます。

あなたはそれからあなたのRESTfulなサーバに尋ねるでしょう: "あなたは私にこのセッションIDのためのリソースをもらえますか?".

認証モードはありません - RESTはステートレスです。セッションを作成し、このセッションIDをパラメータとして使用してリソースを提供するようにサーバーに依頼し、ログアウト時にセッションを削除または期限切れにします。

605
Daniel Vassallo

簡単に言えば、あなたはこれを完全に逆方向にやっています。

どのURLを使うべきかからこれに近づくべきではありません。システムに必要なリソース、それらのリソースの表現方法、およびリソースとアプリケーションの状態との間の相互作用を決定したら、URLは事実上「無料で」入手できます。

引用するには Roy Fielding

REST AP​​Iは、リソースの表現やアプリケーションの状態の駆動に使用されるメディアタイプの定義、または拡張リレーション名やハイパーテキスト対応マークアップの定義に、その記述的な努力のほとんどすべてを費やす必要があります。既存の標準メディアタイプ。関心のあるどのURIにどのメソッドを使用するかを記述するための努力はすべて、メディアタイプの処理規則の範囲内で完全に定義する必要があります(ほとんどの場合、既存のメディアタイプですでに定義されています)。 [ここでの失敗は、帯域外情報がハイパーテキストではなく対話を促進していることを意味します。

人々はいつもURIから始めて、これが解決策だと思います、そしてそれから、彼らはRESTアーキテクチャの重要な概念を見逃す傾向があります、特に、上で引用したように。ハイパーテキストの代わりにインタラクションを推進すること。」

正直に言うと、多くの人がURIやGET、PUT、POSTを見て、RESTは簡単だと思います。 RESTは簡単ではありません。 RPC over HTTPは簡単で、HTTPペイロードを介して転送されるデータの塊を前後に移動させるのは簡単です。ただし、RESTはそれ以上のものです。 RESTはプロトコルに依存しません。 HTTPはとても人気があり、RESTシステムに適しています。

RESTは、メディアタイプ、その定義、およびアプリケーションがハイパーテキストを介してこれらのリソースに利用可能なアクションをどのように推進するか(リンク、効果的)にあります。

RESTシステムのメディアタイプについてはさまざまな見方があります。アプリケーション固有のペイロードを好む人もいれば、既存のメディアタイプをそのアプリケーションに適した役割に引き上げることを好む人もいます。たとえば、一方ではXHTMLのようなものを表現として使用するのに対して、おそらくマイクロフォーマットやその他のメカニズムを通じて、アプリケーションに合わせて設計された特定のXMLスキーマがあります。

どちらのアプローチにも、それぞれの場所があると思います。XHTMLは、人間主導型Webと機械主導型Webの両方に重なるシナリオで非常にうまく機能します。私は商品フォーマットの高揚が潜在的に内容交渉を困難にすることができると思います。 "application/xml + yourresource"は "application/xhtml + xml"よりもメディアタイプとしてはるかに特殊です。後者は、マシンクライアントが実際に興味を持っているかどうかにかかわらず、多くのペイロードに適用できるからではありません。内観せずに決定する。

しかし、XHTMLはWebブラウザとレンダリングが非常に重要である人間のWebで非常にうまく(明らかに)機能します。

あなたの申請書はそのような種類の決定をあなたに導きます。

RESTシステムを設計するプロセスの一部は、派生物とともに、システム内のファーストクラスリソースを発見することです。これは、プライマリリソースでの操作をサポートするために必要なリソースをサポートします。リソースが発見されると、それらのリソースの表現、および表現内のハイパーテキストによるリソースフローを示す状態図が次の課題となります。

ハイパーテキストシステムにおけるリソースの各表現は、実際のリソース表現とそのリソースで利用可能な状態遷移の両方を組み合わせたものであることを思い出してください。各リソースをグラフ内のノードと見なします。リンクはそのノードから他の状態への線です。これらのリンクは、できることだけでなく、実行するために必要なことをクライアントに通知します(適切なリンクは必要なURIとメディアタイプを組み合わせたものです)。

たとえば、次のようになります。

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

あなたのドキュメントは "users"というrelフィールドと "application/xml + youruser"のメディアタイプについて話します。

これらのリンクは冗長に見えるかもしれません、それらはすべて同じURIとほとんど話しています。しかしそうではありません。

これは、 "users"リレーションでは、そのリンクがユーザーのコレクションについて話しているため、コレクションを操作するために統一インターフェースを使用できる(すべてのユーザーを取得するにはGET、すべてのユーザーを削除するにはDELETEなど)

このURLにPOSTした場合は、 "application/xml + usercollection"ドキュメントを渡す必要があります。これにはおそらくドキュメント内に単一のユーザーインスタンスしか含まれないため、ユーザーを追加できます。おそらく、一度にいくつか追加します。おそらくあなたのドキュメントでは、コレクションの代わりに単一のユーザータイプを渡すことができると示唆しているでしょう。

"search"リンクで定義されているように、アプリケーションが検索を実行するために必要なものを見ることができます。検索メディアタイプのドキュメントには、これがどのように振る舞うのか、そして結果として何を期待するのかが書かれています。

ただし、ここでの注意点は、URI自体は基本的に重要ではないということです。アプリケーションはクライアントではなくURIを制御します。いくつかの「エントリポイント」を超えて、あなたのクライアントはその仕事のためにアプリケーションによって提供されたURIに頼るべきです。

クライアントはメディアタイプをどのように操作し解釈するかを知る必要がありますが、どこに行くのかを気にする必要はあまりありません。

これら2つのリンクは、クライアントから見て意味的に同じです。

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

だから、あなたのリソースに焦点を当てます。アプリケーション内での状態遷移と、それがどのようにして最もよく達成されるかに焦点を当てます。

77
Will Hartung

re 1:これはこれまでのところうまくいきます。 "201 Created"ステータスコードと共に、POSTへの応答の一部として、 "Location:"ヘッダーに新しく作成されたユーザーのURIを返すことを忘れないでください。

re 2:GETによる起動は良くない考えで、URIに動詞を含めるのは設計上の匂いです。あなたはGETでフォームを返すことを検討したいかもしれません。 Webアプリでは、これは送信ボタンを持つHTMLフォームです。 APIユースケースでは、アカウントをアクティブにするためにPUTへのURIを含む表現を返すことができます。もちろん、このURIをPOSTの/ usersへの応答に含めることもできます。 PUTを使用することで、あなたの要求がべき等であることが保証されます。つまり、クライアントが成功について確信を持っていない場合は、安全に再度送信することができます。一般的に、動詞をどのようなリソースに変えることができるかについて考えてみましょう(一種の「動詞の名詞化」)。あなたの特定の行動がどのような方法と最も密接に連携しているのかを自問してください。例えば。 change_password - > PUT;非アクティブ化 - >おそらくDELETE。 add_credit - >おそらくPOSTまたはPUT。あなたの表現にそれらを含めることによって、適切なURIをクライアントに向けます。

re 3。新しいステータスコードを発明しないでください。それらが非常に一般的なものであると信じているのでない限り、グローバルに標準化されることに値します。利用可能な最も適切なステータスコードを使うようにしてください(RFC 2616でそれらすべてについて読む)。レスポンスボディに追加情報を含めます。あなたが本当に、あなたが本当に新しいステータスコードを発明したいと本当に確信しているならば、もう一度考えてください。それでもまだ正しいと思われる場合は、少なくとも正しいカテゴリ(1xx - > OK、2xx - > informational、3xx - > redirection; 4xx-> client error、5xx - > server error)を必ず選択してください。新しいステータスコードを発明するのは悪い考えだと私は述べましたか?

re 4。可能であれば、HTTPに組み込まれている認証フレームワークを使用してください。 GDataでGoogleが認証を行う方法を確認してください。一般に、APIキーをURIに入れないでください。スケーラビリティを高め、キャッシングをサポートするためにセッションを避けてみてください - 以前に起こったことのためにリクエストへの応答が異なる場合は、通常、特定のサーバープロセスインスタンスに縛られています。セッション状態をクライアント状態(たとえば、それを後続の要求の一部にする)にするか、または(サーバー)リソース状態にすることによって明示的にする、つまり独自のURIを指定する方がはるかに優れています。

30
Stefan Tilkov

1.あなたは自分のリソースをどのようにデザインするかについて正しい考えを持っています、私見。私は事を変えないでしょう。

2。より多くの動詞でHTTPを拡張しようとするのではなく、基本的なHTTPメソッドとリソースの観点から提案された動詞を減らすことができるものを検討してください。たとえば、activate_login動詞の代わりに、次のようなリソースを設定できます。/api/users/1/login/activeこれは単純なブール値です。ログインを有効にするには、 'true'または1などの文書をPUTしてください。無効にするには、空の文書、または0またはfalseと表示されている文書をPUTします。

同様に、パスワードを変更または設定するには、PUTsを/api/users/1/passwordに変更するだけです。

あなたが何かを追加する必要があるときはいつでも(クレジットのように)POSTsの観点から考えてください。たとえば、/api/users/1/creditsのようなリソースに対してPOSTを実行して、追加するクレジット数を本体に含めることができます。同じリソース上のPUTを使用して、追加ではなく値を上書きすることができます。本体に負の数を持つPOSTは減算されます。

3.基本的なHTTPステータスコードを拡張しないことを強くお勧めします。自分の状況に正確に一致するものが見つからない場合は、最も近いものを選び、応答の詳細にエラーの詳細を入れてください。また、HTTPヘッダーは拡張可能です。あなたのアプリケーションはあなたが好きなすべてのカスタムヘッダを定義することができます。たとえば、私が取り組んだ1つのアプリケーションは、さまざまな状況下で404 Not Foundを返す可能性があります。その理由でクライアントにレスポンス本文を解析させるのではなく、独自のステータスコード拡張を含む新しいヘッダーX-Status-Extendedを追加しました。それで、あなたは以下のような反応を見るかもしれません:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

そのようにしても、WebブラウザのようなHTTPクライアントは通常の404コードで何をすべきかを知ることができ、より洗練されたHTTPクライアントはより特定の情報のためにX-Status-Extendedヘッダを見ることを選ぶことができます。

4.認証には、できればHTTP認証を使うことをお勧めします。しかし、それがあなたにとってより簡単であるなら、私見はクッキーベースの認証を使うことに何の問題もありません。

22
friedo

RESTの基本

RESTには統一されたインターフェース制約があります。つまり、RESTクライアントは実際のRESTサービスのアプリケーション固有の詳細ではなく標準に依存しなければならないため、RESTクライアントは細かく壊れません変更し、おそらくそれは再利用可能になります。

そのため、RESTクライアントとRESTサービスの間に契約があります。基礎となるプロトコルとしてHTTPを使用している場合は、次の規格が契約の一部です。

  • HTTP 1.1
    • メソッド定義
    • ステータスコードの定義
    • キャッシュ制御ヘッダー
    • acceptおよびcontent-typeヘッダー
    • 認証ヘッダー
  • IRI (utf8 URI
  • ボディ(一つ選ぶ)
    • 登録されているアプリケーション固有のMIMEタイプ。 迷路+ xml
    • ベンダー固有のMIMEタイプ、例えば vnd.github + json
    • 付きの汎用MIMEタイプ
      • アプリケーション固有のRDFボキャブ。 ld + jsonヒドラschema.org
      • アプリケーション固有のプロファイル。 hal + json &profile link param(私は思います)
  • ハイパーリンク
    • 何が含まれているべきですか(一つ選んでください)
    • 意味論
      • iANAリンク関係とおそらくカスタムリンク関係を使う
      • アプリケーション固有のRDFボキャブを使う

RESTにはステートレス制約があり、RESTサービスとクライアント間の通信はステートレスでなければならないことを宣言しています。つまり、RESTサービスはクライアントの状態を維持できないため、サーバー側のセッションストレージを確保できません。あなたはすべての要求を認証しなければなりません。そのため、たとえばHTTP基本認証(HTTP標準の一部)は問題ありません。リクエストごとにユーザー名とパスワードを送信するためです。

あなたの質問に答えるために

  1. はい、できます。

    言うまでもなく、クライアントはIRI構造を気にしません、それらは意味論を気にします、なぜなら彼らはリンク関係またはリンクデータ(RDF)属性を持つリンクをたどるからです。

    IRIに関して重要な唯一のことは、単一のIRIが単一のリソースのみを識別しなければならないということです。ユーザーのように、単一のリソースに多くの異なるIRIを持たせることができます。

    /users/123/passwordのようなNice IRIを使用する理由は非常に簡単です。 IRIを理解するだけで、サーバーにルーティングロジックを記述する方がはるかに簡単です。

  2. PUT、PATCH、OPTIONSなどの動詞がもっとありますが、それ以上は必要ありません。新しい動詞を追加する代わりに、新しいリソースを追加する方法を学ぶ必要があります。

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (ログインはステートレスな制約のため、RESTの観点からは意味がありません。)

  3. あなたのユーザーはなぜ問題が存在するのか気にしません。彼らは成功またはエラー、そしておそらく彼らが理解できるエラーメッセージがあるかどうかだけを知りたがっています:例えば、「すみませんが、私たちはあなたの投稿を保存できませんでした」など。

    HTTPステータスヘッダは標準のヘッダです。他のすべては私が思うに体にあるべきです。単一のヘッダは、例えば詳細な多言語エラーメッセージを記述するのに十分ではありません。

  4. ステートレス制約(キャッシュおよび階層化されたシステム制約と共に)は、サービスが確実に適切に拡張されるようにします。クライアントでも同じことができる場合は、サーバー上で何百万ものセッションを維持することを忘れないでください。

    ユーザーがメインクライアントを使用してアクセストークンを付与した場合、そのサードパーティクライアントはアクセストークンを取得します。その後、サードパーティのクライアントはリクエストごとにアクセストークンを送信します。より複雑な解決策があります、例えば、あなたはすべての個々のリクエストに署名することができます、など。詳細についてはOAuthマニュアルをチェックしてください。

関連文献

12
inf3rno

あなたが述べた例のために、私は以下を使うことになるでしょう:

activate_login

POST /users/1/activation

deactivate_login

DELETE /users/1/activation

パスワードを変更する

PUT /passwords(これはユーザーが認証されていることを前提としています)

add_credit

POST /credits(これはユーザーが認証されていることを前提としています)

エラーの場合は、リクエストを受け取った形式で本文にエラーを返すことになります。

DELETE /users/1.xml

レスポンスをXMLで送り返します。JSONなどにも同じことが言えます。

認証にはhttp認証を使うべきです。

11
jonnii
  1. 新しいリソースのURIがどのように見えるかわからない場合はpostを使用します(新しいユーザーを作成し、アプリケーションは新しいユーザーにidを割り当てます)。リソースの更新または作成にはPUTを使用します。 :PUT /myfiles/thisismynewfile.txt)
  2. メッセージ本文にエラーの説明を返す
  3. HTTP認証を使用することができます(それが十分であれば)Webサービスはステートレスです。
6
Arjan

私は(最初の段階として)PUTは既存のエンティティを更新するためだけに使われるべきであることを提案します。 POSTは新しいものを作るために使われるべきです。すなわち.

/api/users     when called with PUT, creates user record

私には正しいとは思わない。ただし、最初のセクションの残りの部分(動詞の使用法)は論理的に見えます。

5
Brian Agnew

冗長ですが、HTTP 1.1のメソッド仕様 http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html からコピーされています。

9.3 GET

GETメソッドとは、Request-URIによって識別される情報(エンティティ形式)を取得することです。 Request-URIがデータ生成プロセスを指す場合、そのテキストが偶然プロセスの出力である場合を除き、応答の実体として返されるのはプロセスのソーステキストではなく生成されたデータです。

要求メッセージがIf-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match、またはIf-Rangeヘッダーフィールドを含む場合、GETメソッドのセマンティクスは「条件付きGET」に変わります。条件付きGETメソッドは、条件付きヘッダーフィールドに記述された状況下でのみエンティティを転送するように要求します。条件付きGETメソッドは、複数の要求を要求したり、クライアントによってすでに保持されているデータを転送したりすることなく、キャッシュされたエンティティを更新できるようにすることで、不要なネットワーク使用を減らすことを目的としています。

要求メッセージがRangeヘッダーフィールドを含む場合、GETメソッドのセマンティクスは「部分的なGET」に変わります。部分的なGETは、セクション14.35で説明されているように、エンティティの一部だけが転送されることを要求します。部分GETメソッドは、クライアントによってすでに保持されているデータを転送することなく、部分的に取得されたエンティティを完了できるようにすることで、不要なネットワーク使用を減らすことを目的としています。

GETリクエストに対するレスポンスは、それがセクション13で説明されているHTTPキャッシングのための要件を満たす場合に限り、キャッシュ可能です。

フォームに使用するときのセキュリティ上の考慮事項については15.1.3節を参照してください。

9.5 POST

POSTメソッドは、Originサーバがリクエストに囲まれたエンティティをリクエスト行のRequest-URIで識別されるリソースの新しい下位オブジェクトとして受け入れることを要求するために使用されます。 POSTは、統一された方法で以下の機能をカバーできるように設計されています。

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

POSTメソッドによって実行される実際の機能はサーバによって決定され、通常はRequest-URIに依存します。投稿されたエンティティは、ファイルがそれを含むディレクトリに従属している、ニュース記事が投稿されているニュースグループに従属している、レコードがデータベースに従属しているのと同じ方法で、そのURIに従属しています。

POSTメソッドによって実行されたアクションは、URIで識別できるリソースにならない可能性があります。この場合、応答に結果を記述するエンティティが含まれているかどうかに応じて、200(OK)または204(No Content)のいずれかが適切な応答ステータスです。

Originサーバでリソースが作成されている場合、レスポンスは201(Created)であるべきであり、リクエストのステータスを記述し新しいリソースを参照するエンティティとLocationヘッダを含んでいるべきです(14.30節を参照)。

応答に適切なCache-ControlまたはExpiresヘッダーフィールドが含まれていない限り、このメソッドに対する応答はキャッシュできません。しかし、303(See See)応答を使用して、ユーザーエージェントにキャッシュ可能なリソースを取得するように指示できます。

POSTリクエストは、セクション8.2に記載されているメッセージ送信要件に従わなければなりません。

セキュリティの考慮事項については15.1.3節を参照してください。

9.6 PUT

PUTメソッドは、囲まれたエンティティが提供されたRequest-URIの下に格納されることを要求します。 Request-URIが既に存在するリソースを参照する場合、囲まれたエンティティはOriginサーバにあるものの修正版と見なされるべきである(SHOULD)。 Request-URIが既存のリソースを指しておらず、そのURIが要求元のユーザーエージェントによって新しいリソースとして定義されることができる場合、OriginサーバはそのURIを使ってリソースを作成することができます。新しいリソースが作成された場合、Originサーバは201(Created)レスポンスを介してユーザエージェントに通知しなければならない(MUST)。既存のリソースが変更された場合、リクエストが正常に完了したことを示すために、200(OK)または204(No Content)の応答コードが送信されるべきです(SHOULD)。リソースがRequest-URIで作成または修正できなかった場合、問題の性質を反映した適切なエラー応答が与えられるべきです(SHOULD)。エンティティの受信者は、理解も実装もしていないContent- *(たとえばContent-Range)ヘッダーを無視してはならず(MUST NOT)、そのような場合には501(未実装)応答を返さなければならない。

リクエストがキャッシュを通過し、Request-URIが1つ以上の現在キャッシュされているエンティティを識別している場合、それらのエントリは古いものとして扱われるべきです(SHOULD)。このメソッドへの応答はキャッシュできません。

POSTとPUTリクエストの基本的な違いは、Request-URIの意味の違いに反映されています。 POST要求内のURIは、囲まれたエンティティを処理するリソースを識別します。そのリソースは、データ受け入れプロセス、他のプロトコルへのゲートウェイ、または注釈を受け入れる別のエンティティなどです。対照的に、PUTリクエストのURIはリクエストに同封されたエンティティを識別します - ユーザエージェントはどんなURIが意図されているか知っていて、サーバはリクエストを他のリソースに適用しようと試みてはいけません。サーバが要求が異なるURIに適用されることを望む場合、

それは301(永久に動かされた)応答を送らなければなりません;ユーザエージェントはそれからリクエストをリダイレクトするかどうかに関してそれ自身の決定をするかもしれません。

単一のリソースは、さまざまなURIによって識別される場合があります。たとえば、記事に「特定の各バージョンを識別するURI」とは別の「現在のバージョン」を識別するURIがあるとします。この場合、一般的なURIに対するPUT要求により、Originサーバによって他のいくつかのURIが定義される可能性があります。

HTTP/1.1は、PUTメソッドがOriginサーバの状態に与える影響を定義していません。

PUT要求は、セクション8.2に記載されているメッセージ送信要件に従わなければなりません。

特定のentity-headerについて特に指定されていない限り、PUTリクエスト内のentity-headersは、PUTによって作成または変更されたリソースに適用されるべきである。

9.7削除

DELETEメソッドは、オリジンサーバがRequest-URIによって識別されたリソースを削除することを要求します。このメソッドはOriginサーバ上での人間の介入(あるいは他の手段)によって上書きされるかもしれません。 Originサーバから返されたステータスコードがアクションが正常に完了したことを示していても、クライアントは操作が実行されたことを保証できません。しかしながら、応答が与えられた時にリソースを削除するかアクセスできない場所に移動させるつもりでない限り、サーバは成功を示すべきではありません(SHOULD NOT)。

応答がステータスを記述するエンティティを含む場合は200(OK)、アクションがまだ実行されていない場合は202(承認済み)、アクションが実行されたが応答が含まれていない場合は204(コンテンツなし)エンティティ。

リクエストがキャッシュを通過し、Request-URIが1つ以上の現在キャッシュされているエンティティを識別している場合、それらのエントリは古いものとして扱われるべきです(SHOULD)。このメソッドへの応答はキャッシュできません。

5
gahooa

RESTリターンコードについて:HTTPプロトコルコードとREST結果を混在させるのは間違っています

しかしながら、私は多くの実装がそれらを混ぜ合わせているのを見ました、そして、多くの開発者は私に同意しないかもしれません。

HTTP戻りコードはHTTP Request自体に関連しています。 REST呼び出しは、ハイパーテキスト転送プロトコル(Hypertext Transfer Protocol)要求を使用して行われ、呼び出されたRESTメソッド自体よりも低いレベルで機能します。 RESTは概念/アプローチであり、その出力はbusiness/logicalresult、HTTP結果コードはtransportoneです。

たとえば、/ users /を呼び出すときに "404 Not found"を返すのは混乱します。

  • URIが間違っている(HTTP)
  • ユーザーが見つかりません(REST)

「403禁止/アクセスが拒否されました」とは、

  • 特別な許可が必要です。ブラウザはユーザ/パスワードを尋ねることによってそれを処理できます。 (HTTP)
  • サーバーに誤ったアクセス許可が構成されています。 (HTTP)
  • 認証される必要があります(REST)

そしてリストは「500サーバーエラー」(Apache/Nginx HTTPスローエラーまたはRESTでのビジネス制約エラー)または他のHTTPエラーなどで続きます。

コードから、失敗の原因、HTTP(トランスポート)の失敗、またはREST(論理)の失敗が何であるかを理解するのは困難です。

HTTPリクエストが物理的に正常に実行された場合、レコードが見つかったかどうかにかかわらず、always200コードが返されるはずです。 URIリソースはfoundであり、httpサーバーによって処理されたためです。はい、それは空のセットを返すかもしれません。 httpの結果として200という空のWebページを受け取ることは可能ですか?

これの代わりに、200 HTTPコードと空の配列/オブジェクトを持つ単純なJSONを返すか、あるいは実行された操作ステータスについて知らせるためにbool result/successフラグを使うことができます。

また、一部のインターネットプロバイダはあなたの要求を傍受して404 httpコードを返す可能性があります。これはあなたのデータが見つからないという意味ではありませんが、トランスポートレベルでは問題があります。

から Wiki

2004年7月、英国の通信事業者BT GroupはCleanfeedコンテンツブロックシステムを導入しました。このシステムは、Internet Watch Foundationによって違法とされる可能性があると識別されたコンテンツに対するリクエストに対して404エラーを返します。他のISPは、同じ状況でHTTP 403「禁止」エラーを返します。検閲を隠すための手段として偽の404エラーを採用することも、タイとチュニジアで報告されています。 2011年の革命以前に検閲が厳しかったチュニジアでは、人々は偽の404エラーの性質に気付き、「見えない検閲官」を表す「Ammar 404」という名前の架空の人物を作成しました。

2
Marcodor