RESTでのPUTとPOSTの比較


5373

HTTP / 1.1仕様によると:

このPOSTメソッドは、元のサーバーが、リクエストで囲まれたエンティティRequest-URIを、Request-Line

つまり、POST作成するために使用されます

このPUTメソッドは、囲まれたエンティティを指定されたの下に保存することを要求しますRequest-URI。がRequest-URI既存のリソースを参照する場合、囲まれたエンティティは、オリジンサーバーに存在するエンティティの変更バージョンと見なされるべきです(SHOULD)。がRequest-URI既存のリソースを指しておらず、そのURIが要求側のユーザーエージェントによって新しいリソースとして定義できる場合、オリジンサーバーはそのURIでリソースを作成できます。」

つまり、PUT作成または置換するために使用されます

では、どれを使用してリソースを作成する必要がありますか?または、両方をサポートする必要がありますか?


56
HTTPbisで定義を使用すると役立つ場合があります-Royは、それらを明確にするためにかなりの作業を行いました。参照:tools.ietf.org/html/...
マーク・ノッティンガム

16
@MarkNottinghamのコメントを最新のリビジョンにするために、HTTPbisで定義されているPOSTPUTを以下に示します。
Marius Butuc

37
この議論は、HTTPメソッドをCRUD操作の観点から説明することによってRESTを単純化しすぎるという一般的な慣習から生じたように思えます。
Stuporman 2013

5
残念ながら、POSTに関する最初の答えは間違っています。違いのより良い説明については私の答えを確認してください:stackoverflow.com/a/18243587/2458234
7hi4g0

23
PUTとPOSTはどちらも安全でない方法です。ただし、PUTはべき等ではなく、POSTはべき等です。-詳細は、restcookbook.com
Dinesh Saini

回答:


4239

全体:

PUTとPOSTの両方を使用して作成できます。

「あなたは何のために行動をとっていますか?」と尋ねる必要があります。使用すべきものを区別するため。質問をするためのAPIを設計しているとしましょう。POSTを使用する場合は、質問のリストに対してそれを行います。PUTを使用する場合は、特定の質問に対してそれを実行します。

両方とも使用できるので、RESTfulな設計でどちらを使用すればよいですか。

PUTとPOSTの両方をサポートする必要はありません。

どちらを使用するかはあなた次第です。ただし、リクエストで参照しているオブジェクトに応じて、適切なオブジェクトを使用することを忘れないでください。

いくつかの考慮事項:

  • 明示的に作成したURLオブジェクトに名前を付けますか、それともサーバーに決定させますか?それらに名前を付ける場合は、PUTを使用します。サーバーに決定させる場合は、POSTを使用します。
  • PUTはべき等であるため、オブジェクトを2回PUTしても効果はありません。これは素晴らしいプロパティなので、可能な場合はPUTを使用します。
  • 同じオブジェクトURLのPUTでリソースを更新または作成できます
  • POSTを使用すると、URLに変更を加える2つの要求を同時に受信でき、それらはオブジェクトの異なる部分を更新する可能性があります。

例:

これに関するSOの別の回答の一部として、私は以下を書きました

役職:

リソースを変更および更新するために使用されます

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

以下はエラーであることに注意してください。

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

URLがまだ作成されていない場合は、名前を指定するときにPOSTを使用して作成しないでください。<new_question>まだ存在しないため、これにより「リソースが見つかりません」エラーが発生するはずです。<new_question> 最初にサーバー上のリソースをPUTする必要があります。

ただし、POSTを使用してリソースを作成するには、次のようにします。

POST /questions HTTP/1.1
Host: www.example.com/

この場合、リソース名が指定されていないことに注意してください。新しいオブジェクトのURLパスが返されます。

プット:

リソースの作成または上書きに使用されます。リソースの新しいURLを指定している間。

新しいリソースの場合:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

既存のリソースを上書きするには:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/

さらに、もう少し簡潔に説明すると、RFC 7231セクション4.3.4 PUTには次のように記載されています(強調が追加されています)。

4.3.4。プット

PUTメソッドは、ターゲットリソースの状態が、要求メッセージのペイロードで囲まれた表現によって定義された状態である createdreplaced、またはその状態で定義されていることを要求します。


1026
PUTがべき等であるという事実を十分に強調することはできないと思います。ネットワークに障害があり、クライアントが要求が成功したかどうかがわからない場合は、2回(または100回)送信するだけでよく、これは1回送信するのとまったく同じ効果があるというHTTP仕様。
イェルクWミッターク

77
@JörgW Mittag:必要ありません。その間にリクエストが変更された場合、2回目は409 Conflictまたは何かを返す可能性があります(他のユーザーまたは最初のリクエスト自体が通過したため)。
Mitar

632
私が間違っていない場合、強調すべきは、PUTがべき等であると定義されていることです。それでも、PUTが正しく動作するようにサーバーを作成する必要があります。おそらく、「PUTによりトランスポートがべき等になるため、キャッシングなどのトランスポートの動作に影響を与える可能性があります。」
Ian Ni-Lewis、

150
@JörgWMittagべき等キャッチフレーズ?「友人を送って送って送ってください、それは結局何の違いもありません。」はどうですか。
James Beninger、2014

39
それらを次のように考えます。PUT=挿入または更新。POST =挿入。したがって、2つのPUTを作成すると、1つの新しいレコードが取得され、2つのPOSTを実行すると、2つの新しいレコードが取得されます。
Eugen Konkov

2218

あなたは言うウェブ上の主張を見つけることができます

どちらもまったく正しくありません。


より良いのは、アクションのべきに基づいてPUTとPOSTのどちらかを選択することです。

PUTはリソースを配置することを意味します。つまり、指定されたURLで利用可能なものをすべて別のものに完全に置き換えます。定義により、PUTはべき等です。何度でも繰り返してください。結果は同じです。x=5べき等です。以前に存在したかどうかに関係なく、リソースをPUTできます(たとえば、作成または更新)。

POSTはリソースを更新するか、補助リソースを追加するか、または変更を引き起こします。POSTはべき等でx++はなく、べき等ではありません。


この引数により、PUTは、作成するもののURLがわかっているときに作成するためのものです。POSTは、作成するもののカテゴリの「工場」またはマネージャーのURLがわかっている場合に使用できます。

そう:

POST /expense-report

または:

PUT  /expense-report/10929

72
べき等が関係している場合はどこでも、他の問題よりも優先されるはずです。間違っていると多くの予期しないバグが発生する可能性があるからです。
Josh、

16
POSTがリソースを更新できる場合、それはどうしてべき等ではありませんか?PUTを使用して生徒の年齢を変更し、それを10倍にした場合、生徒の年齢は1回変更した場合と同じになります。
Jack Ukleja、

28
@Schneider、この場合、あなたのサーバーはべき等性を保証するために特別な努力をしていますが、それはそれを宣伝していません。そのようなPOST要求を再ロードしようとすると、ブラウザーは引き続きユーザーに警告します。
東武

47
@Schneider POSTは補助的なリソースを作成する場合があります。したがって、POST / expense-reportsのように、コレクションにPOSTすることができ、完全に類似している場合でも、送信したリクエストの数と同じ数のエンティティ(費用レポート)がサーバー上に作成されます。自動インクリメントされた主キーを使用して、DBテーブル(/ expense-reports)に同じ行を挿入すると考えてください。データは同じままで、キー(この場合はURI)はサーバーによって生成され、他の挿入(要求)ごとに異なります。したがって、POST効果べき等である可能性がありますが、そうでない場合もあります。したがって、POST はべき等ではありません
スニフ

11
nameとの2つのプロパティを持つエンティティがあるとしdateます。既存のnameand を持つエンティティがありdate、のみを指定してリクエストを行う場合namePUTの適切な動作はdateエンティティのを消去することですが、POSTは指定されたプロパティのみを更新し、指定されていないプロパティはそのままにしておくことがありますリクエストが行われる前。それは正しい/合理的に聞こえますか、それともPUTの不適切な使用ですか?(より適切であるように思われるが、まだ存在しないPATCHへの参照を見ました)?
Jon z

707
  • URLへのPOSTは、サーバー定義の URLに子リソース作成します。
  • URLへのPUTは、クライアント定義の URL でリソース全体を作成または置換します。
  • URLへのPATCHは、そのクライアント定義のURLでリソースの一部更新します。

PUTおよびPOSTに関連する仕様はRFC 2616§9.5ffです。

POSTは子リソース/items作成するため、POST は/itemsリソースの下に存在するリソースを作成します。例えば。/items/1。同じポストパケットを2回送信すると、2つのリソースが作成されます。

PUT、クライアントが認識しているURLでリソースを作成または置換するためのものです

したがって、PUTは、リソースが作成される前にクライアントがURLをすでに知っているCREATEの候補にすぎません。例えば。/blogs/nigel/entry/when_to_use_post_vs_putタイトルがリソースキーとして使用されるため

PUTは、既知のURLにあるリソースが既に存在する場合はそれを置き換えます。そのため、同じリクエストを2回送信しても効果はありません。つまり、PUTの呼び出しはべき等です。

RFCは次のようになります。

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

注: PUTはリソースの更新に(リソース全体を置き換えることによって)主に使用されてきましたが、最近、PUTがリソース全体を置き換えることを指定しているため、既存のリソースの更新にPATCHを使用する動きがあります。RFC 5789。

2018年更新:PUTを回避できるケースがあります。「PUTなしのREST」を参照してください

「PUTなしのREST」手法を使用すると、消費者は新しい「統一された」リクエストリソースを投稿する必要があります。前述のように、顧客の郵送先住所の変更は、新しい「ChangeOfAddress」リソースへのPOSTであり、異なる郵送先住所フィールド値を持つ「顧客」リソースのPUTではありません。

取らThoughtWorks社のプラカシュSubramaniamによるリソースモデリング- REST APIデザイン

これにより、APIは単一のリソースを更新する複数のクライアントによる状態遷移の問題を回避し、イベントソースおよびCQRSとより適切に一致します。作業が非同期で行われる場合、変換をPOSTし、それが適用されるのを待つのが適切なようです。


53
または、フェンスの反対側から:クライアントが結果のリソースのアドレスを決定する場合はPUT、サーバーが決定する場合はPOST。
DanMan、2012年

3
この回答は、@ DanManが非常に単純な方法で指摘した内容をより明確にするために編集する必要があると思います。ここで私が最も価値があると思うのは、PUTはリソース全体を置き換えるためにのみ使用する必要があると述べている最後の注記です。
エルメス

3
PATCHは少なくとも数年間は現実的な選択肢ではありませんが、イデオロギーに同意します。
2014年

4
私は理解しようとしていますが、リソースがまだ存在していないことをクライアントが確実に知っている場合にのみ、PUTを使用して何かを作成することは意味がありますか?ブログの例に従って、2、3年で数百のブログ投稿を作成し、2年前の投稿と同じタイトルを誤って選択したとします。これで、意図していないその投稿が消えて置き換えられました。したがって、PUTを使用して作成すると、クライアントは何が取られ、何が取られないかを追跡する必要があり、事故や意図しない副作用につながるだけでなく、2つのまったく異なることを行うルートを持つことになりますか?
galaxyAbstractor

5
あなたは正しいです。ブログの投稿を既存の投稿と同じURLにPUTすると、その既存の投稿が更新されます(最初にGETで確認することはできます)。これは、タイトルだけをURLとして使用することが悪い考えである理由を示しています。ただし、データに自然なキーがあった場合はどこでも機能します...私の経験ではこれはまれです。または、GUIDを使用した場合
Nigel Thorne、

221

概要:

作成:

次の方法でPUTまたはPOSTの両方で実行できます。

プット

作成した新しいリソースnewResourceId /リソースURI、または下、識別子としてのコレクション

PUT /resources/<newResourceId> HTTP/1.1 

役職

作成/リソースURI、または下に新しいリソースをコレクション。通常、識別子はサーバーから返されます。

POST /resources HTTP/1.1

更新:

次の方法でPUTを使用してのみ実行できます。

プット

/ resources URIまたはcollectionで、既存のリソースIDを識別子として使用してリソースを更新します。

PUT /resources/<existingResourceId> HTTP/1.1

説明:

一般としてRESTとURIを扱うとき、あなたは持っている一般的な、左特定権利ジェネリック医薬品は、通常と呼ばれているコレクション、より具体的な項目を呼び出すことができるリソース。ことに注意してくださいリソースを含めることができるコレクションを

例:

<-一般-特定->

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

あなたはPOSTを使用する場合、あなたはしているいつもの参照のうえコレクションなので、いつでもあなたが言います:

POST /users HTTP/1.1

新しいユーザーをユーザー コレクションに投稿しています

続けて次のようなことを試してみてください:

POST /users/john HTTP/1.1

それは機能しますが、意味的には、ユーザーコレクションの下のジョン コレクションにリソースを追加することを意味しています。

PUTを使用すると、コレクション内のリソースまたは単一のアイテムを参照することになります。だからあなたが言うとき:

PUT /users/john HTTP/1.1

サーバーの更新を指示するか、存在しない場合はユーザーコレクションの下のjohn リソースを作成します

スペック:

仕様の重要な部分をいくつか取り上げます。

役職

POSTのメソッドは、オリジンサーバがその要求に使用されて受け入れるよう要求で囲まれたエンティティの新しい下位のリクエストラインにRequest-URIによって識別されるリソースのを

したがって、コレクションに新しいリソースを作成します。

プット

PUTの同封エンティティはれるメソッド要求格納されている付属のRequest-URIの下。Request-URIが既存のリソースを参照している場合、囲まれたエンティティは、起点サーバーに存在するエンティティの変更バージョンと見なされるべきです(SHOULD)。Request-URIが既存のリソースを指さず、そのURIが要求元のユーザーエージェントによって新しいリソースとして定義できる場合、オリジンサーバーはそのURIでリソースを作成できます

したがって、リソースの存在に基づいて作成または更新します。

参照:


11
この投稿は、POSTが指定されたコレクション(URI)に子として「何か」を追加するのを理解するのに役立ちましたが、PUTは指定されたURIの場所で「何か」を明示的に定義します。
kwah 2013年

3
これが最良の答えです。ここでは、この「POSTはリソースを更新できる」という意味のないことはないと思います。「更新はPUTでのみ実行できる」というあなたの発言が気に入っています。
トーマス

4
いいえ、PUTは更新または作成用ではありません。交換用です。作成の効果のために、何も置き換えることができないことに注意してください。
thecoshman 2015年

2
@ 7hi4g0 PUTは、完全に置き換えて更新するためのものです。つまり、置き換えられます。何も何も入れ替えない、または何かをまったく新しいものに入れ替える。PUTは、マイナーな変更を行うためのものではありません(クライアントにそのマイナーな変更を行わせ、新しいバージョン全体を提供する場合を除いて、同じものはそのままです)。部分的な変更の場合、PATCHが最適な方法です。
thecoshman

1
@thecoshmanできますが、createもここでカバーされていることは明らかではありません。この場合、明示的にすることをお勧めします。
7hi4g0 2015年

175

POST 「ユーザーを作成するための入力です。私のために作成してください」のように、「新規作成」を意味します。

PUT 「これはユーザー5のデータです」のように、「既に存在する場合は挿入、置換」を意味します。

もしPOSTあなたが知らないので、example.com/usersにURLはまだユーザーのは、サーバーがそれを作成します。

あなたは、PUTあなたが/置き換える作成したいので、example.com/users/idする特定のユーザーを。

同じデータで2回POSTすると、IDが異なる2人の同一のユーザーが作成されます。同じデータで2回PUTすると、最初にユーザーが作成され、2回目に同じ状態に更新されます(変更なし)。PUT何度実行しても同じ状態になってしまうため、毎回「同等に強力」、つまりべき等であると言われています。これはリクエストを自動的に再試行するのに役立ちます。ブラウザーの戻るボタンを押しても、「本当に再送してもよろしいですか?」

一般的なアドバイスはPOST、サーバーがURLリソースの生成を制御する必要がある場合に使用することです。PUTそれ以外の場合は使用してください。優先PUT オーバーPOST


12
だらしないと、GETとPOSTの2つの動詞しかないということをよく教えられます。GETして取得し、POSTで変更します。PUTとDELETEもPOSTを使用して実行されました。25年後、PUTが実際に何を意味するのかを尋ねると、おそらく最初は間違っていたという兆候でしょう。RESTの人気により、人々は基本に立ち戻りました。POSTは過度に使用され、現在は誤って教えられています。最良の部分:「同じデータで2回POSTすると、2つの同一の[リソース]が作成されます」。素晴らしい点!
maxpolk

1
どのようにPUTを使用して、IDでレコードを作成できますか(例user 5がまだ存在しない場合の例のように)。どういう意味update, replace if already existsですか?または何か
ルーク

@Coulton:私が書いたものを意味しました。/ users / 5にPUTし、#5がまだ存在しない場合は、ユーザー5を挿入します。
Alexander Torstling 2014年

@Coulton:また、既存のリソース全体の価値PUT置き換えるためにも使用できます。
DavidRR

1
「POSTよりPUTを優先する...」
thecoshman 2015年

173

「実用的な」アドバイスを追加したいと思います。保存しているオブジェクトを取得するための「ID」がわかっている場合は、PUTを使用します。将来の検索や更新を行うために、データベースで生成されたIDを返す必要がある場合などは、PUTを使用してもうまく機能しません。

つまり、既存のユーザー、またはクライアントがIDを生成し、IDが一意であることが確認されているユーザーを保存するには、次のようにします。

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

それ以外の場合は、POSTを使用して最初にオブジェクトを作成し、PUTを使用してオブジェクトを更新します。

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

17
実際に、それはする必要がありますPOST /users。(/usersこれは複数形であることに注意してください。)これは、新しいユーザーを作成し、それを/usersコレクションの子リソースにする効果があります。
DavidRR 2014

6
@DavidRRは公平であり、グループをどのように処理するかは、まったく別の議論です。GET /users理にかなっています、それはあなたが望むように読みますが、それは正しく読みますので、GET /user/<id>またはPOST /user(上記の新しいユーザーのペイロードがあれば)大丈夫でしょう。私はおそらくまだ多元化の側に倒れるでしょう:)
thecoshman

126

POSTを使用して作成し、PUTを使用して更新します。とにかく、Ruby on Railsはそれを行っています。

PUT    /items/1      #=> update
POST   /items        #=> create

4
POST /items定義済みのリソース( 'item')に新しいアイテムを追加します。答えが言うように、「グループを作成する」ことはありません。なぜこれが12票あるのかわかりません。
David J.

RailsはそのままではRESTによる「グループの作成」をサポートしていません。「リソースを作成する」という意味の「グループを作成する」には、ソースコードを使用して行う必要があります。
デビッドJ.

8
これは公正なガイドラインですが、単純化しすぎです。他の回答が述べているように、どちらの方法も作成と更新の両方に使用できます。
Brad Koch

2
少し変更して回答に同意します。POSTを使用してリソースを作成し、PUTを使用してリソースを完全に更新します。部分的な更新の場合、PUTまたはPATCHを使用できます。グループのステータスを更新したいとしましょう。ステータスがリクエストペイロードであるPUT / groups / 1 / statusを使用するか、ペイロード内のアクションに関する詳細を含むPATCH / groups / 1
java_geek

2
これは、リソースの作成にPUT /items/42も有効であることを明確にする必要があります。ただし、クライアントにリソースに名前を付ける権限がある場合のみです。(Railsはクライアントにこの命名特権を許可しますか?)
DavidRR

123

どちらもクライアントからサーバーへのデータ転送に使用されますが、次のような微妙な違いがあります。

ここに画像の説明を入力してください

類推:

  • PUTつまり、それがあった場所に取り、置きます。
  • 郵便局で郵便を送るようにPOST 。

ここに画像の説明を入力してください

ソーシャルメディア/ネットワークの類推:

  • ポストはソーシャルメディア上:私たちは、メッセージを投稿するとき、それは新しいポストを作成します。
  • 入れて、我々はすでに投稿されたメッセージのために(つまり編集を)。

21
@MobileMonいいえ、RESTメソッドはCRUDではありません。
jlr 2016年

1
UPSERTSのPUT
Hola Soy Edu Feliz Navidad

@MobileMon no:新しいリソースを作成し、それを取得する最終的なエンドポイントがわからない場合はPOST。その他の場合はPUT。
Portekoi

67

RESTは非常に高度な概念です。実際、HTTPについてはまったく触れられていません!

HTTPでRESTを実装する方法について疑問がある場合は、Atom Publication Protocol(AtomPub)仕様をいつでも確認できます。AtomPubは、RESTの発明者であり、HTTPの(共同)発明者であるRoy Fieldingからのいくつかの入力により、多くのHTTPとRESTの著名人によって開発されたHTTPでRESTful Webサービスを作成するための標準です。

実際、AtomPubを直接使用することもできます。ブログコミュニティから出たものですが、ブログに限定されるものではありません。HTTPを介して任意のリソースの任意の(ネストされた)コレクションとRESTfulに対話するための汎用プロトコルです。ネストされたリソースのコレクションとしてアプリケーションを表すことができる場合は、AtomPubを使用するだけで、PUTとPOSTのどちらを使用するか、返されるHTTPステータスコード、およびそれらすべての詳細について心配する必要はありません。

これは、AtomPubがリソースの作成について述べなければならないことです(セクション9.2)。

コレクションにメンバーを追加するために、クライアントはPOSTリクエストをコレクションのURIに送信します。


8
PUTがリソースを作成できるようにしても問題はありません。クライアントがURLを提供することを意味することに注意してください。
Julian Reschke、2010

5
PUTがリソースを作成できるようにすることには、非常に問題があります。クライアントがURLを提供します。それがサーバーの仕事です!
Joshcodes 2013年

@JoshcodesクライアントIDを作成するのがサーバーの仕事であるとは限りません。クライアントがリソースIDとしてある種のUUIDを生成できる設計をますます目にしています。この設計は、特に規模を拡大するのに適しています。
ジャスティンオーム

@JustinOhmsクライアントが生成したIDに関するあなたの意見に同意します(補足:2008年頃から私が設計したすべてのシステムでは、クライアントがIDをUUID / Guidとして作成する必要があります)。これは、クライアントがURLを指定する必要があるという意味ではありません。
Joshcodes、2017

1
はい、リソースがすでに存在する場合は、PUTを使用します。ただし、ほとんどすべての場合、リソースはPOSTで作成する必要があり、クライアントはURLを提供しないでください。ロイフィールディングはこの声明に同意しますFWIW:roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Joshcodes

61

HTTP + REST APIを使用してサーバー上にリソースを作成するためにPUTまたはPOSTを使用するかどうかの決定は、URL構造の所有者に基づいています。クライアントにURL構造体を知らせたり、定義に参加させたりすると、SOAから生じた望ましくない結合に似た不要な結合になります。RESTが非常に人気がある理由は、カップリングのタイプを回避することです。したがって、使用する適切な方法はPOSTです。このルールには例外があり、クライアントがデプロイするリソースのロケーション構造に対する制御を保持したい場合に発生します。これはまれであり、他の問題が発生している可能性があります。

この時点で、RESTful-URLが使用されている場合、クライアントはリソースのURLを知っているため、PUTが受け入れられると主張する人もいます。結局のところ、これが正規化された正規化されたRuby on Rails、DjangoのURLが重要な理由です。TwitterAPIを参照してください。これらの人々は、Restful-URLのようなものはなくRoy Fielding自身が次のように述べていることを理解する必要があります

REST APIは、固定リソース名または階層(クライアントとサーバーの明らかな結合)を定義してはなりません。サーバーは、独自の名前空間を自由に制御できる必要があります。代わりに、サーバーがクライアントに適切なURIを構築する方法を指示できるようにします。たとえば、HTMLフォームやURIテンプレートで、メディアタイプとリンク関係内でこれらの指示を定義します。[ここでの障害は、RPCの機能的結合と同等のデータ指向のドメイン固有の標準など、帯域外情報のためにクライアントがリソース構造を想定していることを意味します]

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

RESTful-URLのアイデアは実際にはRESTの違反です。サーバーはURL構造を担当しており、カップリングを回避するためにそれをどのように使用するかを自由に決定できるはずです。これで混乱した場合は、API設計における自己発見の重要性について読んでください。

POSTはべき等ではないため、リソースを作成するためにPOSTを使用する場合は、設計上の考慮事項が伴います。つまり、POSTを数回繰り返しても、毎回同じ動作が保証されるわけではありません。これは、PUTを使用してリソースを作成する必要がないときに怖がらせます。彼らはそれが間違っていることを知っていますが(POSTはCREATEのためです)、彼らはこの問題を解決する方法を知らないのでとにかくそれをします。この問題は、次の状況で示されます。

  1. クライアントはサーバーに新しいリソースをPOSTします。
  2. サーバーは要求を処理し、応答を送信します。
  3. クライアントが応答を受け取ることはありません。
  4. サーバーは、クライアントが応答を受信して​​いないことを認識していません。
  5. クライアントにはリソースのURLがないため(PUTはオプションではありません)、POSTを繰り返します。
  6. POSTはべき等ではなく、サーバー…

ステップ6は、一般的に何をすべきか混乱するところです。ただし、この問題を解決するためにkludgeを作成する理由はありません。代わりに、RFC 2616で指定されているようにHTTPを使用でき、サーバーは次のように応答します。

10.4.10 409コンフリクト

リソースの現在の状態との競合のため、要求を完了できませんでした。このコードは、ユーザーが競合を解決してリクエストを再送信できると予想される状況でのみ許可されます。レスポンスボディは十分に含める必要があります

ユーザーが競合の原因を認識するための情報。理想的には、応答エンティティには、ユーザーまたはユーザーエージェントが問題を修正するのに十分な情報が含まれます。ただし、それは不可能である場合があり、必須ではありません。

競合は、PUTリクエストへの応答で発生する可能性が最も高いです。たとえば、バージョニングが使用されていて、PUTされているエンティティにリソースへの変更が含まれており、それが以前の(サードパーティ)リクエストによる変更と競合する場合、サーバーは409レスポンスを使用して、リクエストを完了できないことを示します。 。この場合、応答エンティティには、応答のContent-Typeで定義された形式で2つのバージョンの違いのリストが含まれている可能性があります。

ステータスコード409 Conflictで返信するのは正しい理由です。

  • すでにシステムにあるリソースと一致するIDを持つデータのPOSTを実行すると、「リソースの現在の状態との競合」になります。
  • 重要な部分は、クライアントがサーバーにリソースがあることを理解し、適切なアクションを実行することです。これは、「ユーザーが競合を解決してリクエストを再送信できることが期待される状況」です。
  • 競合するIDを持つリソースのURLとリソースの適切な前提条件を含む応答は、「ユーザーまたはユーザーエージェントが問題を修正するための十分な情報」を提供します。これはRFC 2616による理想的なケースです。

RFC 7231のリリースに基づいて2616を置き換えるように更新

RFC 7231は2616を置き換えるように設計されており、セクション4.3.3で、POSTの可能な応答について説明しています

POSTの処理結果が既存のリソースの表現と同等である場合、オリジンサーバーは、Locationフィールドに既存のリソースの識別子を含む303(その他を参照)応答を送信することにより、ユーザーエージェントをそのリソースにリダイレクトできます(MAY)。これには、ユーザーエージェントにリソース識別子を提供し、共有キャッシュに適した方法で表現を転送するという利点がありますが、ユーザーエージェントに表現がまだキャッシュされていない場合は追加の要求が発生します。

POSTが繰り返された場合に303を返すだけになりがちです。ただし、その逆が当てはまります。303を返すことは、複数の作成リクエスト(異なるリソースの作成)が同じコンテンツを返す場合にのみ意味があります。たとえば、クライアントが毎回再ダウンロードする必要がない「リクエストメッセージを送信していただきありがとうございます」などです。RFC 7231は、セクション4.2.2でPOSTがべき等ではないことを維持し、POSTを作成に使用する必要があることを維持し続けます。

詳細については、こちらの記事をご覧ください。


409 Conflict応答は、既存のユーザー名で新しいアカウントを作成しようとするような場合に適切なコードでしょうか?具体的には、バージョン管理の競合に409を使用していますが、回答を読んだ後、「重複」リクエストに使用すべきではないかと思います。
エリックB.

@EricB。はい、「リソースの現在の状態との競合のため」と説明した状況では、操作は失敗します。さらに、ユーザーが競合を解決でき、メッセージ本文はユーザー名がすでに存在することをユーザーに通知するだけでよいことを期待するのは妥当です。
Joshcodes、2014

@ジョシュコードはあなたが衝突解決プロセスについてもっと言うことができますか?この場合、ユーザー名がすでに存在する場合、クライアントはエンドユーザーに別のユーザー名を要求する必要がありますか?クライアントが実際にPOSTを使用してユーザー名を変更しようとしている場合はどうなりますか?PUT要求はパラメーターの更新に引き続き使用する必要がありますが、POSTは一度に1つまたは複数のオブジェクトを作成するために使用されますか?ありがとう。
BFar 2015年

@ BFar2ユーザー名がすでに存在する場合、クライアントはユーザーにプロンプ​​トを表示する必要があります。ユーザー名を変更するには、ユーザー名が変更が必要な既に作成されたリソースの一部であると想定すると、正しいのでPUTが使用されます。POSTは作成に使用され、常にPUTが更新に使用されます。
Joshcodes、2015年

短くて効果的な言語を使用して説明することも望ましいスキルです
Junchen Liu

53

RFC 2616のPUTの定義から、このアドバイスが気に入っています

POST要求とPUT要求の基本的な違いは、Request-URIの異なる意味に反映されています。POSTリクエストのURIは、囲まれたエンティティを処理するリソースを識別します。そのリソースは、データを受け入れるプロセス、他のプロトコルへのゲートウェイ、または注釈を受け入れる個別のエンティティである可能性があります。対照的に、PUTリクエストのURIは、リクエストに含まれるエンティティを識別します。ユーザーエージェントは、意図するURIを認識しており、サーバーは他のリソースへのリクエストの適用を試みてはいけません。

これは、PUTが既に名前が付いているリソースに適用するのが最適であり、POSTが既存のリソースの下に新しいオブジェクトを作成する(そしてサーバーに名前を付ける)のに適しているという、他のアドバイスと一致します。

私はこれと、PUTのべき等性の要件を解釈して、次のことを意味します。

  • POSTは、コレクションの下に新しいオブジェクトを作成するのに適しています(作成はべき等である必要はありません)
  • PUTは、既存のオブジェクトの更新に適しています(更新はべき等である必要があります)
  • POSTは、既存のオブジェクトに対するべき等でない更新にも使用できます(特に、全体を指定せずにオブジェクトの一部を変更する-考えてみれば、コレクションの新しいメンバーの作成は、実際にはこの種の特別なケースですコレクションの観点から、更新)
  • PUTは、クライアントがリソースに名前を付けることができる場合にのみ、作成にも使用できます。しかし、RESTクライアントはURL構造についての想定を想定していないため、これは意図されたものの精神ではあまりありません。

3
「POSTは、既存のオブジェクトのべき等でない更新(特に、全体を指定せずにオブジェクトの一部を変更する)にも使用できます」それがPATCHの目的です
Snuggs

48

要するに:

PUTはべき等であり、同じ操作が1回または複数回実行された場合、リソースの状態は同じになります。

POSTはべき等ではないため、操作を1回実行する場合と比較して複数回実行すると、リソースの状態が異なる場合があります。

データベースクエリとの類似

PUT "UPDATE STUDENT SET address =" abc "where id =" 123 ";と同様に考えることができます。

POST "INSERT INTO STUDENT(name、address)VALUES(" abc "、" xyzzz ");のようなものを考えることができます。

学生IDは自動生成されます。

PUTでは、同じクエリが複数回または1回実行された場合、STUDENTテーブルの状態は同じままです。

POSTの場合、同じクエリが複数回実行されると、データベースに複数のStudentレコードが作成され、「INSERT」クエリを実行するたびにデータベースの状態が変化します。

注: PUTでは更新が必要なリソースの場所(既にリソース)が必要ですが、POSTでは必要ありません。したがって、直感的には、POSTは新しいリソースの作成を目的としていますが、PUTは既存のリソースを更新するために必要です。

一部のユーザーは、POSTを使用して更新を実行できることに気付く場合があります。どちらを更新に使用するか、どれを作成に使用するかについて、厳密な規則はありません。繰り返しになりますが、これらは慣例です。直感的に、私は上記の推論に傾倒し、それに従います。


6
以下のためのPUTに似てINSERTまたはUPDATEクエリ
オイゲン・Konkov

1
実際にPUT「UPDATE STUDENT SET address = "abc" where id = "123"と同様に考えることができます; PATCHのステートメントになります。 "UPDATE STUDENT SET address =" abc "、name =" newname "where id =" 123 "は、PUTの正しいアナロジーです
mko

PutはINSERTにも使用できます。たとえば、サーバーが同じファイルを複数回アップロードしようとしていることを検出した場合、リクエストはべき等になります。(新しいファイルのアップロードは行われません)。
kiwicomb123

43

POSTは、メールボックスへの手紙の投稿や、メールキューへのメールの投稿に似ています。PUTは、オブジェクトを陳列棚の穴または棚の上の場所に置くときのようなものです(既知のアドレスがあります)。

POSTでは、QUEUEまたはCOLLECTIONのアドレスに投稿しています。PUTを使用すると、ITEMのアドレスに配置されます。

PUTはべき等です。リクエストは100回送信でき、問題にはなりません。POSTはべき等ではありません。リクエストを100回送信すると、郵便ボックスに100通のメールまたは100通の手紙が届きます。

一般的なルール:アイテムのIDまたは名前がわかっている場合は、PUTを使用します。アイテムのIDまたは名前を受信側から割り当てたい場合は、POSTを使用します。

POSTとPUT


1
いいえ、PUTはURLを知っていることを意味します。IDしかわからない場合は、そのIDをPOSTしてURLを取得します。
Joshcodes 2013年

6
IDはURLの一部であるため、URL(IDを含む)がわかっている場合はPUTを使用します。
Homer6 2013年

いいえ、URLはサーバーによって決定され、IDは必ずしもURLの一部である必要はありません。ロイ・フィールディングがあなたに同じことを教えるか、あなたは彼の論文を読むことができます。
Joshcodes 2013年

@Joshcodes、それはRESTを想定していますか?RESTfulアーキテクチャでは、アイテムIDは/ people / 123のように、間違いなくURLの一部です。RESTのこのサイトが好きです:microformats.org/wiki/rest/urls
Beez

1
@Beez mircoformatsリンクは、サーバーがURLを構造化するための適切な方法を提案していますが、サーバーがURLを決定します。クライアントは二度とありません。これがわからない場合は、私の回答または関連記事を参照しください。
Joshcodes、2014年

39

新しい答え(今はRESTをよく理解している):

PUTは、サービスがクライアントによって識別されたリソースの表現をレンダリングするために今後使用する必要があるコンテンツの単なる説明です。POSTは、サービスが今後どのコンテンツを含む必要があるかを示すステートメントです(おそらく複製される)が、そのコンテンツを識別する方法はサーバー次第です。

PUT xリソースをx識別する場合):「識別されたリソースのコンテンツxを自分のコンテンツに置き換えます。」

PUT xxリソースを識別しない場合):「自分のコンテンツを含む新しいリソースを作成して使用するxそれしてそれを識別します。」

POST x:「私のコンテンツを保存し、そのコンテンツ(他のコンテンツと混合されている可能性があります)を含むリソース(古いまたは新しい)を識別するために使用できる識別子を教えてください。上記のリソースは、識別するリソースと同一または従属である必要がありxます。」" yのリソースはxのリソースに従属します"は通常、ただし必ずしもそうではありませんが、yxのサブパスにして(x = /fooおよびy = /foo/bar)、存在を反映するようにxのリソースの表現を変更します新しいリソースの例、例えばyへのハイパーリンクのリソースといくつかのメタデータ。RESTではURLが不透明であるため、後者のみが優れた設計に不可欠です。サービスを横断するためにクライアント側のURL構築ではなくハイパーメディア使用することになっています

RESTでは、「コンテンツ」を含むリソースなどはありません。サービスが表現を一貫してレンダリングするために使用するデータを「コンテンツ」と呼びます。これは通常、データベースまたはファイル(画像ファイルなど)の関連する行で構成されます。JSONペイロードをSQLステートメントに変換するなど、ユーザーのコンテンツをサービスが使用できるものに変換するのはサービス次第です。

元の答え(読みやすくなる場合があります)

PUT /something/somethingすでに存在する場合):「あなたが持っているものは何でも/something、それを私があなたに与えるもので置き換えてください。」

PUT /something/somethingまだ存在しない場合):「私があなたに与えるものを取り、それをに置いてください/something。」

POST /something:「私があなたに与えたものを取り/something、あなたが終わったときに私にそのURLを教えてくれる限り、好きな場所に置いてください。」


しかし、ID生成メソッドが自動インクリメントになっているときに、PUTを使用して新しいリソースが存在しない場合、それを作成するにはどうすればよいですか?通常、ORMはIDを自動生成します。たとえば、POSTに含める場合と同じようにします。PUTを正しい方法で実装したい場合、ID自動生成を変更する必要があるということですか?答えが「はい」の場合、これは厄介です。
Roni Axelrad 2018

1
@RoniAxelrad:PUTはデータベースの「INSERT OR UPDATE」ステートメントに似ています。ステートメントにキーを含めているため、衝突がないことが保証される場合にのみ適用されます。例えば。ドメインに「自然キー」があるか、GUIDを使用している。POSTは、自動インクリメントキーを使用してテーブルに挿入するようなものです。挿入後に取得したIDをデータベースから通知する必要があります。「INSERT OR UPDATE」が存在する場合、以前のデータが置き換えられることに注意してください。
Nigel Thorne、2018年

@NigelThorneご回答ありがとうございます。したがって、たとえば、ブックID 10をURIでPUTしようとしている場合、PUT books / 10となります。ブックID 10が存在しない場合、ID 10のブックを作成する必要がありますか?作成IDの分子は自動インクリメントなので制御できません。そのような状況ではどうすればよいですか?
Roni Axelrad

1
存在しないIDへの@RoniAxelrad REST PUTは、リソースを作成するサーバーへのリクエストです。それを許可するかどうかは、サーバーが決定します。サーバーが担当しています。「いや、やらない」と答えることができます。ユーザーが十分な権限を持っていない場合はすでにそうしています...など。サーバーが「いいえ」と言っても問題ありません。REST私たちは要求の様々なタイプの意味を定義することができます規則です...あなたのサーバーは、ビジネス・ロジックに基づいて、これらの要求をどのように処理するかを決定した:)それは「ない」それはまだ:) RESTを以下だと言うない場合でも
ナイジェルソーン

38

簡潔な答え:

簡単な経験則:POSTを使用して作成し、PUTを使用して更新します。

長い答え:

役職:

  • POSTは、データをサーバーに送信するために使用されます。
  • リソースのURLが不明な場合に役立ちます

プット:

  • PUTは状態をサーバーに転送するために使用されます
  • リソースのURLがわかっている場合に役立ちます

より長い答え:

それを理解するには、なぜPUTが必要だったのか、POSTが解決できなかったPUTが解決しようとしていた問題は何かを問う必要があります。

RESTアーキテクチャーの観点からは、重要なことは何もありません。私たちはPUTなしでも生活できたでしょう。しかし、クライアント開発者の観点から見ると、彼/彼女の人生はずっと単純になりました。

PUTの前は、クライアントはサーバーが生成したURLを直接、またはサーバーが生成したすべてのURLか、サーバーに送信されるデータがすでに更新されているかどうかを知ることができませんでした。PUTにより、開発者はこれらすべての頭痛の種から解放されました。PUTはべき等であり、PUTは競合状態を処理し、PUTはクライアントにURLを選択させます。


3
あなたの短い答えは非常に間違っているかもしれません。HTTP PUTは、HTTPプロキシで自由に繰り返すことができます。したがって、PUTが実際にSQL INSERTを実行している場合、2回目に失敗する可能性があります。つまり、異なる結果を返し、IDEMPOTENT(PUTとPOSTの違い)ではありません
KamilTomšíkApr

36

Ruby on Rails 4.0は、部分的な更新を行うためにPUTではなく 'PATCH'メソッドを使用します。

RFC 5789はPATCH(1995年以降)について述べています:

相互運用性を向上させ、エラーを防止するには、新しい方法が必要です。PUTメソッドは、完全に新しい本文でリソースを上書きするようにすでに定義されており、部分的な変更を行うために再利用することはできません。そうしないと、プロキシとキャッシュ、さらにクライアントとサーバーでさえ、操作の結果に関して混乱する可能性があります。POSTはすでに使用されていますが、広範な相互運用性はありません(パッチ形式のサポートを検出する標準的な方法はありません)。PATCHは以前のHTTP仕様で言及されていましたが、完全には定義されていません。

Edge Rails:PATCHは、更新のための新しい主要なHTTPメソッドです」と説明しています。


27

既に述べられていることを言い換えると、PUTはリソースを作成するときに、クライアントがURLの最終的な内容を制御することを意味することを覚えておくことは重要なようです。そのため、PUTPOSTの間の選択の一部は、クライアントを信頼して正しい正規化されたURLを提供できるかどうかについてです。 URLスキームが何であれ、首尾一貫したです。

クライアントが正しいことを行うことを完全に信頼できない場合は、POSTを使用して新しいアイテムを作成し、応答でURLをクライアントに送信する方が適切です。


2
これには少し遅れますが、別のWebサイトで同じようなことを言っている人がクリックしてくれました。リソースを作成し、ユーザーが割り当てた名前の代わりに「識別子」として自動インクリメントされたIDを使用している場合、それはPOSTである必要があります。
Ixmatus

2
これは非常に適切ではありません- PUTはまだ対応している限り、非正規名でそれを参照することでリソースを作成することができ、サーバーが返すLocationヘッダ正規のリソース名が含まれています。
Ether

1
@Joshcodesは、同じ基礎となるリソースを参照する多くのURIを持つことができることを忘れないでください。したがって、Etherの発言は健全なアドバイスであり、クライアントはURLにPUTでき(これはのように、よりセマンティックである可能性がPUT /X-files/series/4/episodes/maxあります)、サーバーはその新しいリソース(つまり/X-Ffiles/episodes/91)への短い正規の一意のリンクを提供するURIで応答します
thecoshman

@thecoshman問題は、URL構造がクライアントに属していないことに関する懸念です。セルフディスカバリー(同じくRESTの一部)を読むと、これを明確にするのに役立ちます。
Joshcodesが2015年

@Joshcodesはそのロジックにより、URLの提供に関係する必要がないため、クライアントはPUTを使用して作成しないでください。ええと...サーバーがPUTへのURLを提供し、クライアントがそれを配置したい場合を除いて... "PUT / comments / new"のようなもので、サーバーは "204 / comments / 234532"と応答するかもしれませんが、それは少し思えますRPCは私に、クライアントは/ commentsにPOSTするだけです...
thecoshman

24

非常に簡単な方法で、私はFacebookタイムラインの例を取り上げています。

ケース1:タイムラインに何かを投稿すると、それは新しいエントリです。したがって、この場合、POSTメソッドはべき等ではないため、POSTメソッドを使用します。

ケース2:友達があなたの投稿に初めてコメントした場合、データベースに新しいエントリが作成されるため、POSTメソッドが使用されます。

ケース3:友達がコメントを編集した場合、この場合、コメントIDがあったため、データベースに新しいエントリを作成する代わりに、既存のコメントを更新します。したがって、このタイプの操作では、べき等であるため、PUTメソッドを使用します。*

1行で、POSTを使用してデータベースに新しいエントリを追加しPUTを使用してデータベース内の何かを更新します。


4
コメントがユーザーID、作成日、コメントメッセージなどのプロパティを持つオブジェクトであり、編集時にコメントメッセージのみが更新される場合、ここでパッチを実行する必要がありますか?
Habeeb Perwad 2017

PUTは、既存のリソースが更新されているため、コメントを更新するためにFBによって使用されます。これは、PUTが行う(リソースを更新する)ものです。POSTとは対照的に、PUTは偶然にも偶然です。べき等であるHTTP動詞はエラー処理に影響を与えますが、使用法を指示するものではありません。より詳細な説明のために私の答えを参照してください。stackoverflow.com/questions/630453/put-vs-post-in-rest/...
Joshcodes

21

最も重要な考慮事項は信頼性です。POSTメッセージが失われた場合、システムの状態は未定義です。自動回復は不可能です。PUTメッセージの場合、最初の再試行が成功するまで、状態は未定義です。

たとえば、POSTでクレジットカードトランザクションを作成することはお勧めできません。

リソースに自動生成されたURIがある場合でも、生成されたURI(空のリソースを指す)をクライアントに渡すことにより、PUTを使用できます。

その他の考慮事項:

  • POSTは、含まれているリソース全体のキャッシュされたコピーを無効にします(整合性が向上します)
  • PUT応答はキャッシュ可能ですが、PUT応答はキャッシュできません(Content-Locationと有効期限が必要です)
  • PUTは、Java ME、古いブラウザ、ファイアウォールなどではサポートされていません。

これは誤りです。POSTの場合、状態も定義されていないだけで最初に成功した再試行まで。次に、サーバーがPOST(メッセージが到着していない)を受け入れるか、重複ID(メッセージが到着した、応答が失われた)、またはその他の有効な応答に対して409の競合をスローします。
Joshcodes、2014

一般に、POST操作は2つの操作が1つの操作と同じ効果を持つという保証がないため、ユーザーエージェントはPOST操作を安全に再試行できません。「ID」という用語はHTTPとは関係ありません。URIはリソースを識別します。
Hans Malherbe、2014

ユーザーエージェントは、POST操作を必要なだけ「安全に」再試行できます。重複IDエラー(リソースにIDがあると想定)または重複データエラー(それが問題であり、リソースに IDがないと想定)を受け取ります。
Joshcodes、2014

前髪は壁に向かいます。HTTPには信頼性の問題に対する解決策がありません。これは十分に理解されておらず、あまり議論されておらず、Webアプリケーションの大部分で提供されていません。@Joshcodesこの質問に対する答えがあります。私は基本的にハンスに同意します。問題があります。
bbsimonbb 2018年

@ bbsimonbb、HTTPには、堅牢で十分に文書化された一連のエラー応答があります。この質問に対する私の答え(stackoverflow.com/questions/630453/put-vs-post-in-rest/…)は、仕様に従ってhttpを使用して一貫性を実現する方法をカバーしています。
Joshcodes、

17

このトピックを初めて読む読者は、あなた何をすべきかについての無限の議論、そして経験からの教訓の相対的な欠如に衝撃を受けます。SOAPよりもRESTが「推奨」されているという事実は、経験からの高度な学習だと思いますが、そこから進歩したに違いないのでしょうか。それは2016年です。ロイの論文は2000年にありました。私たちは何を開発しましたか?楽しかったですか?統合は簡単でしたか?サポートするには?スマートフォンや不安定なモバイル接続の増加に対応しますか?

MEによれば、実際のネットワークは信頼できません。リクエストのタイムアウト。接続がリセットされます。ネットワークは一度に数時間または数日間ダウンします。電車は、モバイルユーザーを乗せてトンネルに入ります。特定の要求(この説明で時々認められるように)では、要求が途中で水に落ちたり、応答が途中で水に落ちたりすることがあります。これらの状況で、実質的なリソースに対して直接PUT、POST、およびDELETEリクエストを発行することは、常に私を少し残忍で素朴なものとして感じました。

HTTPは、要求と応答の確実な完了を保証するためには何も行いません。これは、ネットワーク対応アプリケーションの仕事であるため、問題ありません。このようなアプリケーションを開発する場合、フープをジャンプしてPOSTの代わりにPUTを使用し、重複するリクエストを検出した場合にサーバー上で特定の種類のエラーを発生させることができます。クライアントに戻って、これらのエラーを解釈し、再フェッチ、再検証、再投稿するために、フープをジャンプする必要があります。

または、これを行うことができます。安全でないリクエストを一時的なシングルユーザーリソースと見なします(アクションと呼びましょう)。クライアントは、リソースへの空のPOSTを使用して、実体リソースに対して新しい「アクション」を要求します。POSTはこれにのみ使用されます。新たに作成されたアクションのURIを安全に保持すると、クライアントはアクションURIに安全でない要求をPUTします。は、ターゲットリソースはなく、。アクションを解決して「実際の」リソースを更新することは、APIの仕事であり、信頼性の低いネットワークから切り離されています。

サーバーはビジネスを行い、応答返し、合意されたアクションURIに対して格納します。何かがうまくいかない場合、クライアントはリクエストを繰り返し(自然な動作です!)、サーバーがすでにそれを確認している場合は、保存されているレスポンス繰り返し、それ以外は何もしません

あなたは約束との類似性をすぐに見つけるでしょう:私たちは何かをする前に結果のプレースホルダーを作成して返します。また、promiseのように、アクションは一度だけ成功または失敗する可能性がありますが、その結果は繰り返しフェッチできます。

何よりも、送信アプリケーションと受信アプリケーションに、一意に識別されたアクションをそれぞれの環境の一意性に関連付ける機会を与えます。そして、クライアントに責任ある行動を要求し、強制することができます!リクエストを好きなだけ繰り返しますが、既存のアクションから最終的な結果が得られるまで、新しいアクションを生成しないでください。

そのため、多くの厄介な問題が解消されます。挿入リクエストを繰り返しても重複は作成されず、データを取得するまで実際のリソースは作成されません。(データベースの列はnull可能ではありません)。繰り返される更新リクエストは、互換性のない状態にヒットすることはなく、その後の変更を上書きしません。クライアントは、何らかの理由(クライアントのクラッシュ、応答の欠落など)で元の確認を(再)フェッチしてシームレスに処理できます。

連続した削除リクエストは、404エラーに遭遇することなく、元の確認を表示および処理できます。予定よりも時間がかかる場合は、暫定的に対応でき、クライアントが最終的な結果を確認できる場所があります。このパターンの最も良い部分は、カンフー(パンダ)プロパティです。私たちは弱点を取り、クライアントが応答を理解できないときはいつでも要求を繰り返し、それを強みに変えます:-)

これがRESTfulではないと言う前に、RESTの原則が尊重される多くの方法を検討してください。クライアントはURLを作成しません。APIは、セマンティクスが少し変更されたとしても、検出可能なままです。HTTP動詞が適切に使用されている。これを実装するための大きな変更であると思われる場合は、経験からそうではないことがわかります。

保存するデータが大量にあると思われる場合は、話してみ​​ましょう。一般的な更新の確認は、キロバイトの端数です。HTTPは現在、1〜2分で確実に応答します。アクションを1週間しか保存しなくても、クライアントは追いつく十分な機会があります。ボリュームが非常に多い場合は、専用の酸に準拠したキーバリューストア、またはインメモリソリューションが必要になる場合があります。


1
応答を保存することは、セッションを維持するようなものではありませんか?(水平)スケーリングの問題が発生します。
Saurabh Harwande

17

他の人から提案された違いに加えて、もう1つ追加したいと思います。

ではPOSTの方法あなたは、体ののparamsを送ることができますform-data

ではPUTの方法あなたは、体ののparamsを送信する必要がありますx-www-form-urlencoded

ヘッダ Content-Type:application/x-www-form-urlencoded

これによると、PUTメソッドでファイルまたはマルチパートデータを送信できません

編集する

コンテンツタイプ「application / x-www-form-urlencoded」は、非ASCII文字を含む大量のバイナリデータまたはテキストを送信する場合は非効率的です。コンテンツタイプ「multipart / form-data」は、ファイル、非ASCIIデータ、およびバイナリデータを含むフォームの送信に使用する必要があります。

つまり、提出する必要がある場合

ファイル、非ASCIIデータ、およびバイナリデータ

あなたはPOSTメソッドを使うべきです


3
なぜこれは賛成されなかったのですか?真の場合、これは重要な区別ではありませんか?
Iofacture

2
ユーザープロファイルの写真のアップロードを含む、プロファイル更新用のAPIを実装するときに直面しました。それから私はそれをポストエンド、Ajax、PHP curl、laravel 5.6をバックエンドとしてテストしました。
Rohit Dhiman

14

RESTサービスでHTTP POSTメソッドとHTTP PUTメソッドをいつ使用するかについては常に混乱があるようです。ほとんどの開発者は、CRUD操作をHTTPメソッドに直接関連付けようとします。これは正しくなく、CRUDの概念をHTTPメソッドに単純に関連付けることはできないと私は主張します。あれは:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

CRUD操作のR(etrieve)およびD(elete)は、それぞれHTTPメソッドGETおよびDELETEに直接マップできることは事実です。ただし、混乱はC(reate)およびU(update)操作にあります。作成にPUTを使用できる場合もあれば、POSTが必要になる場合もあります。あいまいさは、HTTP PUTメソッドとHTTP POSTメソッドの定義にあります。

HTTP 1.1仕様によれば、GET、HEAD、DELETE、およびPUTメソッドはべき等である必要があり、POSTメソッドはべき等ではありません。つまり、リソースに対して1回または何度も実行でき、常にそのリソースの同じ状態を返すことができる場合、操作はべき等です。一方、べき等ではない操作では、リソースの変更された状態を1つの要求から別の要求に返すことができます。したがって、非べき等操作では、リソースの同じ状態を受け取る保証はありません。

上記のべき等の定義に基づくと、RESTサービスにHTTP PUTメソッドを使用するのではなく、HTTP PUTメソッドを使用することに私の見解は次のとおりです。

The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).

どちらの場合も、これらの操作を複数回実行しても同じ結果が得られます。つまり、操作を複数回要求してもリソースは変更されません。したがって、真のべき等演算です。次の場合は、HTTP POSTメソッドを使用します。

The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.

結論

CRUD操作をRESTサービスのHTTPメソッドに直接関連付けてマッピングしないでください。HTTP PUTメソッドとHTTP POSTメソッドの使用は、その操作のべき等の側面に基づく必要があります。つまり、操作がべき等の場合は、HTTP PUTメソッドを使用します。操作がべき等でない場合は、HTTP POSTメソッドを使用します。


2
更新=> HTTP POST:POSTは更新用ではありません
Premraj

@premrajあなたはBurhanが作ってはいけないと言っていると仮定しました。つまり、CRUD、REST、およびHTTPを統合しています。これらが定義されているRFC 7231を読むと、HTTPプロトコルでは、POSTの定義によって更新が確実に許可されることがわかります。それ以外のことを言うのは、RESTの制約だけです。
IAM_AL_X

13

オリジンサーバーはそのURIでリソースを作成できます

したがって、リソースの作成にはPOSTを使用しますが、必要ではありませんがPUTを使用します。両方をサポートする必要はありません。私にとってはPOSTで十分です。したがって、これは設計上の決定です。

あなたの引用が述べたように、IRIに割り当てられたリソースがないの作成にPUTを使用し、とにかくリソースを作成したいとします。たとえば、PUT /users/123/password通常は古いパスワードを新しいパスワードに置き換えますが、パスワードがまだ存在しない場合(たとえば、新しく登録されたユーザーまたは禁止されたユーザーを復元することによって)、パスワードを作成するために使用できます。


PUTの使用方法の数少ない良い例の1つを提供できたと思います。
thecoshman

12

次のもので着陸します。

PUTは、URIで識別されるリソースを指します。この場合は、更新しています。これは、リソースを参照する3つの動詞の一部です-削除して、他の2つになります。

POSTは基本的に自由形式のメッセージであり、その意味は「帯域外」と定義されています。メッセージをリソースをディレクトリに追加すると解釈できる場合は問題ありませんが、基本的には、送信(投稿)するメッセージを理解して、リソースで何が起こるかを知る必要があります。


PUTおよびGETおよびDELETEはリソースを参照するため、定義によりべき等でもあります。

POSTは他の3つの機能を実行できますが、その後、リクエストのセマンティクスは、キャッシュやプロキシなどの仲介者で失われます。これは、リソースのセキュリティの提供にも当てはまります。投稿のURIは、適用するリソースを必ずしも示しているわけではないためです(ただし、可能です)。

PUTは作成である必要はありません。リソースがまだ作成されていない場合、サービスはエラーになる可能性がありますが、それ以外の場合は更新します。またはその逆-リソースを作成する可能性がありますが、更新は許可されません。PUTについて必要なのは、特定のリソースを指し、そのペイロードがそのリソースの表現であることだけです。PUTが成功するとは、(干渉がなければ)GETが同じリソースを取得することを意味します。


編集:もう1つ、PUTで​​作成できますが、作成する場合は、IDを自然なIDにする必要があります。このように、2回PUTすると、2番目の書き込みは最初の書き込みの更新になります。これはべき等ですです。

IDが生成される場合(たとえば、新しい従業員ID)、同じURLを持つ2番目のPUTは、べき等ルールに違反する新しいレコードを作成します。この場合、動詞はPOSTとなり、メッセージ(リソースではない)は、このメッセージで定義された値を使用してリソースを作成することになります。


9

「GET」がべき等であるはずの「PUT」がべき等であるという意味で、セマンティクスは異なると想定されています。つまり、同じ正確なPUTリクエストを複数回実行でき、結果は1回だけ実行したかのようになります。

私が最も広く使用されており、最も有用であると思う規則について説明します。

特定のURLでリソースをPUTすると、そのURL、またはそれらの行に沿って何かが保存されます。

特定のURLのリソースにPOSTすると、多くの場合、関連する情報がそのURLに投稿されます。これは、URLのリソースがすでに存在することを意味します。

たとえば、新しいストリームを作成する場合は、それをあるURLにPUTできます。ただし、メッセージを既存のストリームにPOSTする場合は、そのURLにPOSTします。

ストリームのプロパティの変更については、PUTまたはPOSTを使用して行うことができます。基本的に、操作がべき等の場合にのみ「PUT」を使用します。それ以外の場合はPOSTを使用します。

ただし、最新のすべてのブラウザがGETまたはPOST以外のHTTP動詞をサポートしているわけではないことに注意してください。


あなたがPOSTを説明するのは、実際にはPATCHがどのように動作するかです。POSTは、「post to mailing list」のように、「append」に似たものを意味するはずです。
Alexander Torstling 2014年

8

ほとんどの場合、次のように使用します。

  • リソースをコレクションにPOSTする
  • collection /:idで識別されるリソースをPUTします

例えば:

  • 役職 /アイテム
  • PUT / items / 1234

どちらの場合も、リクエストの本文には、作成または更新されるリソースのデータが含まれます。ルート名から、POSTはべき等ではない(3回呼び出すと3つのオブジェクトが作成されます)が、PUTはべき等である(3回呼び出すと結果は同じになる)ことは明らかです。PUTは「upsert」操作(作成または更新)によく使用されますが、変更にのみ使用したい場合は、常に404エラーを返すことができます。

POSTはコレクションに新しい要素を「作成」し、PUTは指定されたURLの要素を「置換」しますが、PUTを部分的な変更に使用することは非常に一般的な方法です。つまり、既存のリソースの更新と本文に含まれるフィールドのみを変更します(他のフィールドは無視します)。これは技術的に正しくありません。RESTピュリストになりたい場合、PUTはリソース全体を置き換え、部分的な更新にはPATCHを使用する必要があります。すべてのAPIエンドポイントで動作が明確で一貫している限り、個人的にはあまり気にしません。

RESTは、APIをシンプルに保つための一連の規則とガイドラインです。「RESTfull」ボックスをチェックするだけで複雑な回避策が発生する場合は、目的を達成できていません;)


7

これらを説明するために不可知論的な方法がある可能性がありますが、それはウェブサイトへの回答からのさまざまなステートメントと矛盾しているようです。

非常に明確で、ここで直接説明しましょう。Web APIを使用する.NET開発者の場合、事実は(Microsoft APIドキュメントから)、 http://www.asp.net/web-api/overview/creating-web-apis/creating-a-webです。 -api-that-supports-crud-operations

1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 -  UPDATE = PUT, there are **NO** multiple answers for that question period.

確かに「POST」を使用して更新できますが、所定のフレームワークでレイアウトされた規則に従ってください。私の場合は.NET / Web APIなので、PUTはUPDATE用ですであり、議論はありません。

これが、AmazonとSun / JavaのWebサイトリンクですべてのコメントを読むすべてのMicrosoft開発者に役立つことを願っています。


7

簡単なルールは次のとおりです。

URLへのPUTは、そのURLにあるリソースを更新または作成するために使用する必要があります。

URLへのPOSTは、他の(「従属」)URLにあるリソース、またはHTTP経由で検索できないリソースを更新または作成するために使用する必要があります。


1
PUTは更新用ではなく、置換用です。作成するには、何も何も置換しないことに注意してください。POSTは、いかなる形の更新も絶対に行いません。
thecoshman 2015年

2
http仕様はそれを言っていますか?それとも、何か他のものに基づいてコメントしていますか?
アダムグリフィス

それは常識です、何を更新しているのかわからないときに、どのように更新しますか?POSTは、新しいリソースを作成するためのものです。
thecoshman

2
thecoshman-ここでセマンティクスを悪用しています-いくつかの違いはありますが、同じリソースである場合、置換は更新である可能性があります。置換は、置換を使用して同じリソースを変更する場合にのみ、putに対して有効です。特に「新しい」リソースに自然なIDがない場合は、新しい別のリソースへの置き換えは無効です(古いものを削除して、新しいものを追加しますか?)。POST、OTOHは、作成、更新、置換、および削除できるものです-投稿の使用は、「割引を適用する」など、解釈するメッセージがあるかどうかによって異なり、リソースを変更する場合としない場合があります論理。
Gerard ONeill、2016

2番目のコメントについては、リソースを「取得」し、必要なフィールドを変更して、元に戻しますか?または、リソースが別のソースからのものであるが、ナチュラルID(外部ID)を使用している場合はどうですか?putは、元のデータが変更されたときにURLのリソースを自然に更新します。
Gerard ONeill、2016

6

データベース操作に精通している場合は、

  1. 選択する
  2. インサート
  3. 更新
  4. 削除する
  5. マージ(既存の場合は更新、そうでない場合は挿入)

私が使用してPUT操作や使用などのマージおよび更新のためのPOST挿入のために。


5

実際には、POSTはリソースの作成に適しています。新しく作成されたリソースのURLは、Location応答ヘッダーで返されます。リソースを完全に更新するには、PUTを使用する必要があります。これらはRESTful APIを設計する際のベストプラクティスであることを理解してください。HTTP仕様自体は、リソースの作成/更新に関するいくつかの制限があるPUT / POSTの使用を制限していません。ベストプラクティスをまとめたhttp://techoctave.com/c7/posts/71-twitter-rest-api-dissectedご覧ください。


ほとんどすべての場合、このすべてのノイズを読み取ることから、あなたはボールの上にいるように見えます。ただし、作成/更新ではなく、PUTをreplaceメソッドとして参照する必要があります。私はそれが何をするのかをよりよく説明していると思います。
thecoshman 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.