http put方法 post差異 - REST中的PUT與POST





15 Answers

你可以在網上找到斷言

兩者都不對。

最好是根據動作的idempotence性在PUT和POST之間進行選擇。

PUT意味著放置一個資源 - 用不同的東西完全替換給定URL上的任何可用資源。 根據定義,PUT是冪等的。 你喜歡這麼多次,結果是一樣的。 x=5是冪等的。 無論以前是否存在,您都可以投入資源(例如,創建或更新)!

POST更新資源,添加輔助資源或導致更改。 POST不是冪等的,就像x++不是冪等的一樣。

通過這個論點,PUT用於在您知道要創建的事物的URL時創建。 當您知道要創建的事物類別的“工廠”或管理員的URL時,可以使用POST創建。

所以:

POST /expense-report

要么:

PUT  /expense-report/10929
post請求 api vs

根據HTTP / 1.1規範:

POST方法用於請求源服務器接受請求中包含的實體作為Request-Line Request-URI標識的資源的新下級

換句話說, POST用於創建

PUT方法請求將所包含的實體存儲在提供的Request-URI 。 如果Request-URI引用已經存在的資源,則封閉的實體應該被視為駐留在源服務器上的實體的修改版本。 如果Request-URI沒有指向現有資源,並且該URI能夠被請求用戶代理定義為新資源,則源服務器可以使用該URI創建資源。

也就是說, PUT用於創建或更新

那麼,應該使用哪一個來創建資源? 或者需要支持兩者?




摘要:

創建:

可以通過以下方式使用PUT或POST執行:

使用newResourceId作為標識符,在/ resources URI或集合下創建新資源。

PUT /resources/<newResourceId> HTTP/1.1 

POST

在/ resources URI或集合下創建新資源。 通常,服務器返回標識符。

POST /resources HTTP/1.1

更新:

只能通過以下方式使用PUT執行:

使用existingResourceId作為標識符,在/ resources URI或集合下更新資源。

PUT /resources/<existingResourceId> HTTP/1.1

說明:

在處理REST和URI時,您可以在左側使用泛型 ,在右側使用 特定的。 泛型通常稱為集合 ,更具體的項稱為資源 。 請注意, 資源可以包含集合

例子:

< - generic - specific - >

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

您要將新用戶發佈到users 集合

如果你繼續嘗試這樣的事情:

POST /users/john HTTP/1.1

它會起作用,但從語義上說,你想要將資源添加到users 集合下的john 集合中

一旦您使用PUT,您就可以在集合中引用資源或單個項目。 所以當你說:

PUT /users/john HTTP/1.1

您告訴服務器更新,或者創建它是否不存在, 用戶 集合下的john 資源

規格:

讓我重點介紹一下規範的一些重要部分:

POST

POST方法用於請求源服務器接受請求中包含的實體作為請求行中Request-URI標識的資源的下級

因此,在集合上創建新資源

PUT方法請求將所包含的實體存儲在提供的Request-URI下。 如果Request-URI引用已經存在的資源,則封閉的實體應該被視為駐留在源服務器上的實體的修改版本 。 如果Request-URI 沒有指向現有資源,並且該URI 能夠被請求用戶代理定義為資源 ,則源服務器可以使用該URI 創建資源。

因此,基於資源的存在來創建或更新。

參考:




POST表示“創建新”,如“以下是創建用戶的輸入,為我創建”。

PUT表示“插入,替換,如果已經存在”,如“這是用戶5的數據”。

您發佈到example.com/users,因為您還不知道用戶的URL,您希望服務器創建它。

由於您要替換/創建特定用戶,因此請輸入example.com/users/id。

使用相同數據發布兩次意味著創建兩個具有不同ID的相同用戶。 使用相同數據進行兩次輸入會使用戶創建第一次並在第二次將其更新為相同狀態(無更改)。 因為你在PUT之後無論你執行它多少次都會得到相同的狀態,所以每次都被稱為“同樣有效” - 冪等。 這對於自動重試請求很有用。 當您按下瀏覽器上的後退按鈕時,不再“您確定要重新發送”嗎?

一般建議是在需要服務器控制資源的URL生成時使用POST。 否則使用PUT。 首選PUT over POST。




REST是一個非常高級的概念。 事實上,它甚至根本沒有提到HTTP!

如果您對如何在HTTP中實現REST有任何疑問,可以隨時查看Atom發布協議(AtomPub)規範。 AtomPub是一個使用HTTP編寫RESTful webservices的標準,由許多HTTP和REST傑出人員開發,其中一些來自REST的發明者和HTTP本身(共同)發明者Roy Fielding的輸入。

實際上,您甚至可以直接使用AtomPub。 雖然它來自博客社區,但它絕不僅限於博客:它是一種通用協議,用於通過HTTP與任意資源的任意(嵌套)集合進行REST交互。 如果您可以將應用程序表示為嵌套的資源集合,那麼您可以使用AtomPub而不用擔心是使用PUT還是POST,要返回的HTTP狀態代碼以及所有這些詳細信息。

這就是AtomPub關於資源創建的說法(第9.2節):

要將成員添加到集合,客戶端會將POST請求發送到集合的URI。




兩者都用於客戶端到服務器之間的數據傳輸,但它們之間存在細微差別,它們是:

比喻:

  • PUT即拿走並放置它的位置。
  • POST作為郵局發送郵件。




POST就像在郵箱中發信或將電子郵件發送到電子郵件隊列。PUT就像你把一個物體放在一個小房間或一個架子上的地方(它有一個已知的地址)。

使用POST,您將發佈到QUEUE或COLLECTION的地址。使用PUT,您可以使用ITEM的地址。

PUT是冪等的。您可以發送請求100次,這無關緊要。POST不是冪等的。如果您發送請求100次,您將在郵政信箱中收到100封電子郵件或100封信件。

一般規則:如果您知道項目的ID或名稱,請使用PUT。如果您希望接收方分配項目的ID或名稱,請使用POST。




新答案(現在我更了解REST):

PUT僅僅是服務應該從現在開始用於呈現客戶端識別的資源的表示的內容的陳述; POST是一個聲明,說明服務從現在開始應該包含哪些內容(可能是重複的),但服務器應該如何識別該內容。

PUT x(如果x標識resource):“替換由x我的內容標識的資源的內容。”

PUT x(如果x未標識資源):“創建包含我的內容的新資源,並使用x它來識別它。”

POST x:“存儲我的內容並給我一個標識符,我可以使用它來識別包含所述內容的資源(舊的或新的)(可能與其他內容混合在一起)。所述資源應該與x標識的資源相同或從屬。” “ ÿ的資源是從屬於X的資源”是通常但不通過使一定實施ÿ的子路徑X(例如X = /fooÿ = /foo/bar)和修改的表示(S)X的資源,以反映是否存在一個新資源的例子,例如帶有y的超鏈接的資源和一些元數據。只有後者對於良好的設計才是真正必不可少的,因為在REST中URL是不透明的 - 你應該使用超媒體而不是客戶端URL構造來遍歷服務。

在REST中,沒有包含“內容”的資源。我將“內容”稱為服務用於一致地呈現表示的數據。它通常由數據庫中的一些相關行或文件(例如圖像文件)組成。服務可以將用戶的內容轉換為服務可以使用的內容,例如將JSON有效負載轉換為SQL語句。

原始答案(可能更容易閱讀)

PUT /something(如果/something已經存在的話):“拿走你所擁有的一切,/something並用我給你的東西取而代之。”

PUT /something(如果/something還不存在的話):“把我給你的東西放進去吧/something。”

POST /something:“ /something只要你在完成後給我的URL ,就把我給你的東西放在任何你想要的地方。”




簡答:

簡單的經驗法則:使用POST創建,使用PUT進行更新。

答案很長:

POST:

  • POST用於將數據發送到服務器。
  • 資源的URL未知時很有用

放:

  • PUT用於將狀態傳輸到服務器
  • 知道資源的URL時很有用

更長的答案:

為了理解它,我們需要質疑為什麼PUT是必需的,PUT試圖解決的問題是POST不能解決的問題。

從REST架構的角度來看,沒有一個重要。我們也可以在沒有PUT的情況下生活。但從客戶端開發人員的角度來看,這使他/她的生活變得更加簡單。

在PUT之前,客戶端無法直接知道服務器生成的URL或者是否已生成任何URL,或者是否已經更新了要發送到服務器的數據。PUT解除了所有這些頭痛的開發人員。PUT是冪等的,PUT處理競爭條件,PUT允許客戶端選擇URL。




最重要的考慮因素是可靠性。如果POST消息丟失,則係統狀態未定義。自動恢復是不可能的。對於PUT消息,只有在第一次成功重試之前,狀態才是未定義的。

例如,使用POST創建信用卡交易可能不是一個好主意。

如果您的資源上碰巧有自動生成的URI,您仍然可以通過將生成的URI(指向空資源)傳遞給客戶端來使用PUT。

其他一些考慮:

  • POST使整個包含資源的緩存副本無效(更好的一致性)
  • POST請求時PUT響應不可緩存(需要內容位置和到期)
  • PME受Java ME,舊瀏覽器,防火牆等的支持較少



對於什麼時候使用HTTP POST而不是HTTP PUT方法來解決REST服務似乎總是存在一些混淆。大多數開發人員會嘗試將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(更新)操作。在某些情況下,可以使用PUT進行創建,而在其他情況下,則需要POST。模糊性在於HTTP PUT方法與HTTP POST方法的定義。

根據HTTP 1.1規範,GET,HEAD,DELETE和PUT方法必須是冪等的,POST方法不是冪等的。也就是說,如果操作可以在資源上執行一次或多次並且總是返回該資源的相同狀態,則該操作是冪等的。而非冪等操作可以將資源的修改狀態從一個請求返回到另一個請求。因此,在非冪等操作中,不能保證一個人將獲得相同的資源狀態。

基於上面的冪等定義,我使用HTTP PUT方法與使用HTTP POST方法進行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方法。




對這個主題不熟悉的讀者會被關於你該做什麼的無休止討論以及相對缺乏經驗教訓所震驚。我認為,REST比SOAP更“優先”的事實是從經驗中獲得高水平的學習,但我們必須從那裡取得進步?這是2016年。羅伊的論文是在2000年。我們開發了什麼?它有趣嗎?是否易於集成?支持?它會處理智能手機和移動連接的崛起嗎?

根據ME,現實生活中的網絡是不可靠的。請求超時。連接已重置。網絡一次下降數小時或數天。火車進入隧道與移動用戶搭乘。對於任何給定的請求(在所有這些討論中偶爾都會承認),請求可以在途中落入水中,或者響應可以在返回途中落入水中。在這些情況下,直接針對實質性資源發出PUT,POST和DELETE請求一直讓我覺得有點野蠻和天真。

HTTP沒有做任何事情來確保請求響應的可靠完成,這很好,因為這恰好是網絡感知應用程序的工作。開發這樣的應用程序,你可以跳過箍使用PUT而不是POST,然後更多的箍在服務器上發出某種錯誤,如果你檢測到重複的請求。回到客戶端,然後你必須跳過箍來解釋這些錯誤,重新獲取,重新驗證和重新發布。

或者您可以這樣做:將您的不安全請求視為短暫的單用戶資源(讓我們稱之為操作)。客戶端在實體資源上請求新的“操作”,對資源進行空POST。 POST將僅用於此目的。一旦安全地擁有新鮮動作的URI,客戶端就將不安全的請求PUT發送到動作URI,而不是目標資源。解決操作並更新“真實”資源恰好是API的工作,並且在這裡與不可靠的網絡分離。

服務器執行業務,返迴響應並將其存儲在約定的操作URI中。如果出現任何問題,客戶端會重複請求(自然行為!),如果服務器已經看到它,它會重複存儲的響應並且不執行任何其他操作

您將很快發現與promises的相似性:我們在執行任何操作之前創建並返回結果的佔位符。也像承諾一樣,動作可以成功或失敗一次,但其結果可以重複獲取。

最重要的是,我們為發送和接收應用程序提供了將唯一標識的操作與其各自環境中的唯一性相關聯的機會。我們可以開始要求並執行!來自客戶的負責任行為:盡可能多地重複您的請求,但在您擁有現有結果的確定結果之前不要生成新的操作。

因此,許多棘手的問題消失了。重複插入請求不會創建重複項,並且在我們擁有數據之前,我們不會創建真實資源。(數據庫列可以保持不可為空)。重複更新請求不會遇到不兼容的狀態,也不會覆蓋後續更改。客戶端可以(重新)獲取並無縫處理原始確認,無論出於何種原因(客戶端崩潰,響應丟失等)。

連續刪除請求可以查看和處理原始確認,而不會遇到404錯誤。如果事情花費的時間超過預期,我們可以暫時回复,我們有一個地方,客戶可以檢查確定的結果。這種模式中最好的部分是它的功夫(熊貓)屬性。我們採取了一個弱點,即客戶在不理解響應的情況下重複請求的傾向,並將其變為強度 :-)

在告訴我這不是RESTful之前,請考慮REST原則的眾多方式。客戶端不構造URL。雖然語義上有一點變化,但API仍然是可發現的。適當使用HTTP謂詞。如果你認為這是一個巨大的改變,我可以從經驗告訴你,它不是。

如果您認為要存儲大量數據,那就讓我們來談談:典型的更新確認只是一個千字節的一小部分。HTTP目前為您提供一兩分鐘的明確回應。即使您只存儲一周的行動,客戶也有足夠的機會趕上。如果您的產量非常高,您可能需要一個專用的符合酸的鍵值存儲或內存解決方案。




語義應該是不同的,因為“PUT”,如“GET”應該是冪等的 - 意思是,你可以多次執行相同的PUT請求,結果就像你只執行一次一樣。

我將描述我認為最廣泛使用且最有用的約定:

當您在特定URL上放置資源時,會發生的事情是它應該保存在該URL,或者沿著這些行保存。

當您對特定URL上的資源進行POST時,通常會向該URL發布相關信息。這意味著URL上的資源已經存在。

例如,當您想要創建新流時,可以將其設置為某個URL。但是,當您要將消息發佈到現有流時,請POST到其URL。

至於修改流的屬性,可以使用PUT或POST執行此操作。基本上,只有當操作是冪等時才使用“PUT” - 否則使用POST。

但請注意,並非所有現代瀏覽器都支持GET或POST以外的HTTP謂詞。




雖然可能有一種不可知的方式來描述這些,但它似乎與網站答案中的各種陳述相衝突。

讓我們在這裡非常明確和直接。如果您是使用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網站鏈接所有評論的Microsoft開發人員。




實際上,POST適用於創建資源。應在Location響應頭中返回新創建的資源的URL。PUT應該用於完全更新資源。請理解這些是設計RESTful API時的最佳實踐。這樣的HTTP規範不限制使用PUT / POST,但有一些限制來創建/更新資源。請查看http://techoctave.com/c7/posts/71-twitter-rest-api-dissected,總結最佳實踐。




除了別人建議的差異之外,我想再添加一個。

POST方法中,你可以發送身體參數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方法






Related