web-dev-qa-db-ja.com

PUT vs. POST に REST

HTTP/1.1仕様によると:

POSTメソッドは、Originサーバがリクエストに含まれるエンティティを、Request-URIRequest-Lineで識別されるリソースの新しい下位オブジェクトとして受け入れることを要求するために使用されます。

つまり、POST create に使用されます。

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

つまり、PUT 作成または更新 に使用されます。

それで、リソースを作成するためにどれが使われるべきですか?それともどちらかをサポートする必要がありますか?

4925
alex

全体:

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

あなたは「あなたは何をして行動をとっていますか」と尋ねなければなりません。何を使うべきかを区別するため。質問をするためのAPIを設計しているとしましょう。あなたがPOSTを使いたいのなら、あなたはそれを質問のリストにするでしょう。もしあなたがPUTを使いたいのなら、あなたはそれを特定の質問に対してするでしょう。

両方を使うことができるので、RESTful設計ではどちらを使うべきですか:

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

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

いくつかの考慮事項:

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

例:

これに関するSOの別の回答の一部として次のように書きました

POST:

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

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

以下はエラーです。

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

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

POSTを使ってリソースを作成するには、このようなことができます。

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

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

PUT:

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

新しいリソースの場合

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

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

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/
3880
Brian R. Bondy

あなたは言うWeb上でアサーションを見つけることができます

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


より良いのは、アクションの idempotence に基づいて、PUTとPOSTの間で選択することです。

_ put _ はリソースを置くことを意味します - 与えられたURLで利用可能なものはすべて別のものに置き換えます。定義上、PUTはべき等です。あなたが好きなだけそれをしなさい、そして結果は同じです。 x=5はべき等です。リソースが以前に存在しているかどうかにかかわらず、リソースをPUTできます(たとえば、作成または更新)。

_ post _ は、リソースの更新、補助リソースの追加、または変更を加えます。 x++がべき乗ではないという点で、POSTはべき乗ではありません。


この引数により、PUTはあなたが作成するもののURLを知っているときに作成するためのものです。 POSTは、あなたが作成したいもののカテゴリの "factory"またはマネージャのURLを知っているときに作成するために使用することができます。

そう:

POST /expense-report

または

PUT  /expense-report/10929
2053
Cheeso
  • POST URLへ子リソースを作成サーバー定義URLで。
  • PUT URLにリソースを作成/置換クライアント定義URLで完全に。
  • PATCH URLへリソースの更新partそのクライアント定義URL。

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

POSTは子リソースを作成しますなので、POST to /items/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はリソースを更新するために主に使用されています(全体を置換することにより)が、最近では既存のリソースを更新するためにPATCHを使用する動きがあります。 RFC 5789。

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

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

REST APIデザイン-ThoughtworksのPrakash Subramaniamによるリソースモデリング から取得

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

668
Nigel Thorne

概要:

作成:

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

プット

/ resources URIまたはcollectionの下に、newResourceIdを識別子としてTHE新しいリソースを作成します。

PUT /resources/<newResourceId> HTTP/1.1 

POST

/ resources URIの下にA新しいリソース、またはcollectionを作成します。通常、識別子はサーバーによって返されます。

POST /resources HTTP/1.1

更新:

onlyは、次の方法でPUTで実行できます。

プット

/ resources URIの下のexistingResourceIdまたはcollectionでリソースを更新します。

PUT /resources/<existingResourceId> HTTP/1.1

説明:

RESTおよびURIを一般的に扱う場合、leftgenericがあり、rightspecificがあります。 genericsは通常collectionsと呼ばれ、より多くのspecificアイテムはresourceと呼ばれます。 リソースにはコレクションを含めることができます。

例:

<-ジェネリック-特定->

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

userscollectionに新しいユーザーを投稿しています。

続けて次のようなことを試してみると:

POST /users/john HTTP/1.1

それは動作しますが、意味的には、userscollectionの下のjohncollectionにリソースを追加したいということです。

PUTを使用すると、おそらくcollection内のresourceまたは単一のアイテムを参照します。だからあなたが言うとき:

PUT /users/john HTTP/1.1

userscollectionの下のjohnresourceをサーバーの更新に通知するか、存在しない場合は作成します。

仕様:

仕様のいくつかの重要な部分を強調します。

POST

POSTメソッドは、Originサーバーにacceptリクエストのnewsubordinateとして囲まれたエンティティをリクエストするために使用されますRequest-LineのRequest-URIで識別されるリソース

したがって、collectionに新しいresourceを作成します。

プット

PUTメソッドは、指定されたRequest-URIで囲まれたエンティティがstoredであることを要求します。 Request-URIがalready existingリソースを参照する場合、囲まれたエンティティは、Originサーバーにあるものの修正バージョンと見なされるべきです(SHOULD)。 Request-URIが既存のリソースを指し、そのURIがnewresourceとして定義されている有能である場合要求元のユーザーエージェントの場合、OriginサーバーはそのURIでリソースをcreateできます。

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

参照:

204
7hi4g0

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

そのため、既存のユーザ、またはクライアントが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
169
ThaDon

「これはユーザーを作成するための入力です。私のために作成します」のように、POSTは「create new」を意味します。

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

ユーザーのURLがまだわからないので、example.com/usersにPOSTを入力し、サーバーに作成させてください。

specific ユーザーを置き換え/作成するため、example.com/users/idにPUTします。

同じデータで2回POSTするということは、IDが異なる2人の同じユーザーを作成することを意味します。同じデータで2回PUTすると、最初のユーザーが作成され、2回目は同じ状態に更新されます(変更なし)。何回実行してもPUTの後は同じ状態になるので、毎回「等しく効力がある」と言われます - べき等性。これはリクエストを自動的に再試行するのに便利です。ブラウザの戻るボタンを押しても、「再送信してもよろしいですか」ということはもう必要ありません。

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

162

作成するにはPOSTを、更新するにはPUTを使用してください。それがRuby on Railsのやり方です。

PUT    /items/1      #=> update
POST   /items        #=> create
121
Tim Sullivan

どちらもクライアントからサーバーへのデータ転送に使用されますが、両者にはわずかな違いがあります。

Enter image description here

類推:

  • PUTすなわちtake and put があったところ。
  • post officeに送信メールとしてPOSTします。

enter image description here

ソーシャルメディア/ネットワークのアナロジー:

  • 投稿 ソーシャルメディア上:投稿すると新しい投稿が作成されます。
  • すでに投稿したメッセージに対して (編集)を入力します。
88
Premraj

RESTは very の高レベルの概念です。実際には、HTTPについてもまったく言及していません。

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

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

これは、AtomPubがリソース作成について言うことです(セクション9.2)。

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

65
Jörg W Mittag

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

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

REST APIは固定のリソース名や階層を定義してはいけません(クライアントとサーバーの明らかな結合)。サーバーは自分の名前空間を自由に制御できる必要があります。代わりに、HTML形式やURIテンプレートで行われているように、メディアタイプやリンク関係の中でそれらの命令を定義することによって、サーバーがクライアントに適切なURIの構成方法を指示できるようにします。 [ここでの失敗は、クライアントがドメイン固有の標準など、帯域外の情報によるリソース構造を想定していることを意味します。これは、RPCの機能カップリングと同等のデータ指向のものです]。

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

RESTful-URLという概念は、サーバーがURL構造を担当しているため、実際にはRESTに違反しており、カップリングを回避するための使用方法を自由に決めることができます。これがわかりにくい場合は、API設計における自己検出の重要性について読んでください。

POSTはべき等ではないので、リソースを作成するためにPOSTを使用することは設計上の考慮事項があります。これはPOSTを数回繰り返すことが毎回同じ振る舞いを保証しないことを意味します。 これは、必要なときにリソースを作成するためにPUTを使用するように人々を怖がらせます。彼らはそれが間違っていることを知っています(POSTはCREATEのためです)が、彼らはこの問題を解決する方法を知らないので彼らはとにかくそうします。この懸念は、次の状況で実証されています。

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

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

10.4.10 409対立

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

ユーザーが競合の原因を認識するための情報。理想的には、レスポンスエンティティは、ユーザーまたはユーザーエージェントが問題を解決するのに十分な情報を含むでしょう。ただし、それは不可能である可能性があり、必須ではありません。

競合は、PUT要求に応答して発生する可能性が最も高いです。たとえば、バージョン管理が使用されていて、PUTされているエンティティに、以前の(サードパーティの)要求によって行われたものと競合するリソースへの変更が含まれている場合、サーバーは409応答を使用して要求を完了できないことを示します。 。この場合、レスポンスエンティティはレスポンスContent-Typeで定義されたフォーマットで2つのバージョン間の違いのリストを含むでしょう。

のため、ステータスコード409 Conflictで返信するのが正しい方法です。

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

2672を置き換えるためのRFC 7231のリリースに基づく更新

RFC 7231 は2616を置き換えるように設計されており、 セクション4.3.3 にはPOSTに対する次の可能な応答が記述されています。

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

POSTが繰り返される場合には、単純に303を返すのが魅力的かもしれません。しかし、その逆は真実です。 303を返すことは、複数の作成要求(異なるリソースを作成すること)が同じコンテンツを返す場合にのみ意味があります。例としては、クライアントが毎回再ダウンロードする必要がないことを示す「リクエストメッセージを送信していただきありがとうございます」などがあります。 RFC 7231はまだセクション4.2.2でPOSTはべき乗ではないと主張し、POSTが作成のために使われるべきであると主張し続けています。

これに関するより詳しい情報は、 article を読んでください。

58
Joshcodes

RFC 2616によるPUTの定義 :から、このアドバイスが好きです。

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

これは他のアドバイスにもかかわらず、PUTはすでに名前を持っているリソースに最もよく適用され、POSTは既存のリソースの下に新しいオブジェクトを作成するのに適しています。

私はこれとPUTのべき等性要件を次のように解釈します。

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

要するに:

_ put _ は冪等です。同じ操作を1回または複数回実行した場合、リソースの状態は同じになります。

_ post _ は冪等ではありません。この場合、1回の実行と比較して、操作が複数回実行されるとリソースの状態が異なる可能性があります。

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

_ put _ "UPDATE STUDENT SET address =" abc "id =" 123 "のように考えることができます。

_ post _ "INSERT INTO STUDENT(名前、住所)VALUES(" abc "、" xyzzz ");のようなものを考えることができます。

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

PUTでは、同じクエリが複数回または1回実行されても、STUDENTテーブルの状態は変わりません。

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

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

POSTを使って更新できるということを思いつく人もいます。どちらを更新に使用するのか、どちらを作成に使用するのかという厳密な規則はありません。やはりこれらは慣習であり、直感的に私は上記の推論に慣れてそれに従います。

45
bharatj

POSTは、メールボックスへの手紙の投稿、またはメールキューへのメールの投稿のようなものです。 PUTはあなたが物をたるんだ穴や棚の上の場所に置いたときのようなものです(それは既知の住所を持っています)。

POSTを使用して、QUEUEまたはCOLLECTIONのアドレスに投稿しています。 PUTで、あなたはITEMのアドレスに入れています。

PUTはべき等です。あなたは100回要求を送ることができます、そしてそれは関係ありません。 POSTはべき等ではありません。リクエストを100回送信すると、郵便箱に100通の電子メールまたは100文字の手紙が届きます。

原則として、アイテムのIDまたは名前がわかっている場合は、PUTを使用してください。アイテムのIDまたは名前を受け取り側によって割り当てたい場合は、POSTを使用してください。

POST versus PUT

42
Homer6

新しい回答(今ではRESTの理解度が向上しました):

PUTは、クライアントが識別したリソースの表現をレンダリングするために、今後サービスが使用するコンテンツのステートメントです。 POSTは、今後サービスに含まれるコンテンツのステートメントです(おそらく複製されます)が、そのコンテンツを識別する方法はサーバー次第です。

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

PUT xxがリソースを識別しない場合): "コンテンツを含む新しいリソースを作成し、xを使用して識別します。"

POST x:「コンテンツを保存し、そのコンテンツ(他のコンテンツと混合される可能性がある)を含むリソース(古いまたは新しい)を識別するために使用できる識別子を提供します。リソースはx識別します。」 「yのリソースはxのリソースに従属する」は、通常はyxのサブパス(例:x= /foo andy= /foo/bar)およびxのリソースの表現を変更して、新しいリソースの存在を反映します。 yのリソースといくつかのメタデータへのハイパーリンク付き。 RESTではURLが不透明であるため、優れた設計には後者のみが本当に不可欠です-サービスをトラバースするには、クライアント側のURL構築の代わりに se hypermedia を使用することになっています。

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

元の答え(読みやすいかもしれません)

PUT /something/somethingが既に存在する場合): "/somethingにあるものをすべて取り、私が提供したものに置き換えます。"

PUT /something/somethingがまだ存在しない場合): "提供したものを取り、/somethingに配置します。"

POST /something: "完了したらURLを提供する限り、私が提供したものを取り、/somethingの下に任意の場所に置きます。"

38
Jordan

短い答え:

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

ロングアンサー:

役職:

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

プット:

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

長い答え:

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

RESTアーキテクチャの観点からは、重要なことはありません。私たちもPUTなしで暮らしていたかもしれません。しかし、クライアント開発者の観点からは、それは彼/彼女の人生をずっと簡単にしました。

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

36
ishandutta2007

Ruby on Rails 4.0は部分的な更新をするためにPUTの代わりに 'PATCH'メソッドを使うでしょう。

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

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

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

35
germanlinux

すでに述べたことを言い換えると、 _ put _ はクライアントが _ url _ を作成するときに何になるかを制御することを意味することを覚えておくことが重要です。リソース。そのため、 _ put _ _ post _ の間の選択の一部は、正しい、正規化された _ url _ を提供するためにクライアントをどれだけ信頼できるかということになります。あなたのURLスキームが何であっても。

正しいことをするためにクライアントを完全に信頼できない場合は、 _ post _ を使用して新しい項目を作成し、その応答でURLをクライアントに送り返すことがより適切です。

26
skillet-thief

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

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

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

ケース3:あなたの友人が彼のコメントを編集した場合、この場合、彼らはコメントIDを持っていたので、彼らはデータベースに新しいエントリーを作成する代わりに既存のコメントを更新します。したがって、この種の演算にはPUT法を使用します。これはべき乗であるためです。

単一行で、 _ post _ を使用して データベースに/ - 新しいエントリ を追加し、 _ put _ update に追加します。

21
UniCoder

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

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

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

その他の考慮事項

  • POSTは含まれているリソース全体のキャッシュコピーを無効にします(より良い一貫性)
  • POST件がPUTレスポンスである間はキャッシュできません(Content-Locationと有効期限が必要です)。
  • PUTは、例えば以下によってサポートされていません。 Java ME、古いブラウザ、ファイアウォール
20
Hans Malherbe

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

MEによると、実際のネットワークは信頼性に欠けています。リクエストのタイムアウト。接続がリセットされます。ネットワークは一度に数時間または数日間ダウンします。列車は、モバイルユーザーが乗ったトンネルに入ります。特定の要求(この説明で時々確認される)については、要求が途中で水に落ちたり、応答が途中で水に落ちたりする可能性があります。 これらの条件では、実質的なリソースに対してPUT、POSTおよびDELETEリクエストを直接発行することは、常に少し残酷で素朴なものとして私を襲った。

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

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

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

約束との類似性をすぐに見つけることができます。結果を出す前にプレースホルダーを作成して返します。また、約束のように、アクションは一度だけ成功または失敗することがありますが、その結果は繰り返し取得できます。

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

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

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

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

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

14
bbsimonbb

POSTサービスに対してHTTP RESTと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回または複数回実行され、常にそのリソースの同じ状態を返すことができる場合、その操作は冪等です。一方、冪等でない操作は、あるリクエストから別のリクエストへとリソースの変更された状態を返すことができます。したがって、冪等でない操作では、リソースの同じ状態を受け取るという保証はありません。

上記のべき等定義に基づいて、POSTサービスにHTTP RESTメソッドを使用するのではなく、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メソッドを使用してください。

14
Burhan

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

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

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

13
inf3rno

私は次のものを使って着陸するつもりです:

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

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


PUT、GET、DELETEはリソースを参照するので、それらも定義上は同じです。

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

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


編集:もう一つ - PUTが作成することができますが、その場合そのIDは自然なIDである必要があります - AKAは電子メールアドレスです。そうすれば、2回PUTを実行したときに、2番目のプットは最初のプットの更新になります。これは べき等 になります。

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

11
Gerard ONeill

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

_ post _ methodでは、ボディパラメータをform-dataで送信できます。

_ put _ メソッドでは、ボディパラメータをx-www-form-urlencodedで送信する必要があります

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

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

_編集_

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

あなたが提出しなければならないならば、それは意味します

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

_ post _ methodを使うべきです

11
Rohit Dhiman

意味は異なります。つまり、 "PUT"は "GET"がべき数に等しいと想定されているため、まったく同じPUTリクエストを複数回実行でき、結果は1回だけ実行した場合と同じです。

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

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

特定のURLのリソースにPOSTすると、そのURLに関連情報を投稿することがよくあります。これは、そのURLのリソースがすでに存在していることを意味します。

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

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

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

9

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

  • _ post _ コレクション内のリソース
  • _ put _ collection /で識別されるリソース/:id

例えば:

  • _投稿_ /アイテム
  • _ put _ / items/1234

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

POSTはコレクション内の新しい要素を "作成"し、PUTは与えられたURLの要素を "置き換え"ますが、部分的な変更にPUTを使うのはとても一般的なやり方です。既存のリソースを更新し、本文に含まれるフィールドのみを変更する(他のフィールドは無視する)ためだけに使用します。 REST純粋主義者になりたいのであれば、これは技術的には間違っています。PUTはリソース全体を置き換え、部分的な更新にはPATCHを使用する必要があります。個人的には、動作がすべてのAPIエンドポイントにわたって明確で一貫している限り、あまり気にしません。

覚えておいて、RESTはあなたのAPIを単純に保つための規約とガイドラインのセットです。 「RESTfull」ボックスをチェックするだけの複雑な回避策になった場合は、目的を無効にしていることになります。

7
tothemario

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

ここではっきりとした説明をしましょう。 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
Tom Stickel

これが簡単なルールです:

URLへの _ put _ を使用して、そのURLに配置できるリソースを更新または作成します。

URLへの _ post _ は、他の( "従属")URLに配置されている、またはHTTP経由で配置できないリソースを更新または作成するために使用されます。

6
Adam Griffiths

データベース操作に慣れている方は、

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

私はPUTをMerge and update like操作に使い、POSTを挿入に使います。

6
Rajan

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

5
java_geek

POST: 新しいリソースを作成するために使用します。これは、自動インクリメントIDを持つINSERT(SQLステートメント)のようなものです。応答部分には、新しく生成されたIDが含まれています。

POSTはレコードの更新にも使用されます。

PUT: 新しいリソースを作成するために使用しますが、ここでは識別キーを知っています。これは、IDキーを事前に知っているINSERT(SQLステートメント)のようなものです。応答部分では何も送信しません。

PUTはリソースの更新にも使用されます。

3
sushil pandey

それで、リソースを作成するためにどれが使われるべきですか?それともどちらかをサポートする必要がありますか?

あなたはPATCHを使うべきです。次のような質問のリストをパッチします。

PATCH /questions HTTP/1.1

作成するオブジェクトを含むリストを使って

[
    {
        "title": "I said semantics!",
        "content": "Is this serious?",
        "answer": "Not really"
    }
]

これはPATCHリクエストです。

  • 既存の リソースのリスト まったく新しいものを提供せずに コンテンツを変更する
  • あなたはあなたの新しい質問の状態を存在しないものから既存のものに変更します 全てのデータを提供せずに (おそらくサーバはidを追加します)。

この方法の大きな利点は、1つの要求を使用して複数のエンティティを作成できることです。それらをすべてリストに含めるだけで済みます。

これはPUTが明らかにできないことです。それはHTTPの台所の流しであり、基本的にすべてを行うことができるので、あなたは複数のエンティティを作成するためにPOSTを使うことができます。

不利な点は、おそらくこの方法でPATCHを誰も使用していないことです。私はそれを発明したばかりなのではないかと思いますが、良い議論を提供したことを願っています。

カスタムHTTP動詞が許可されているので、代わりにCREATEを使用することができます。それはそれらがいくつかのツールでは動作しないかもしれないということです。

意味論に関して、CREATEは私見の唯一の正しい選択です、他はすべて丸穴の四角い釘です。あいにく、私たちが持っているのは丸穴だけです。

2
maaartinus

このPUT対POSTの質問では共有されなかった興味深い点もあると思います。

JavaScriptなしで動作するWebアプリケーションが必要な場合(たとえば、誰かがLynxなどのコマンドラインブラウザーやNoScriptやuMatrixのようなブラウザーアドオンを使用している場合)、POSTを使用して送信する必要がありますHTMLフォームはGETおよびPOST HTTP要求のみをサポートするため、データ。

基本的にプログレッシブエンハンスメント( https://en.wikipedia.org/wiki/Progressive_enhancement )を使用して、JavaScriptの有無にかかわらずWebアプリケーションをどこでも動作させる場合、次のようなHTTPメソッドを使用することはできませんHTTPバージョン1.1でのみ追加されたPUTまたはDELETE。

0
baptx