Câu hỏi PUT so với POST trong REST


Theo thông số HTTP / 1.1:

Các POST phương pháp được sử dụng để yêu cầu máy chủ gốc chấp nhận thực thể được đính kèm trong yêu cầu dưới dạng một cấp dưới mới của tài nguyên được xác định bởi Request-URI bên trong Request-Line

Nói cách khác, POST đã từng tạo nên.

Các PUT phương thức yêu cầu rằng thực thể đính kèm được lưu trữ theo cung cấp Request-URI. Nếu Request-URI đề cập đến một tài nguyên đã tồn tại, thực thể kín được NÊN được coi là một phiên bản sửa đổi của một trong những cư trú trên máy chủ gốc. Nếu Request-URI không trỏ đến tài nguyên hiện có và URI đó có khả năng được định nghĩa là tài nguyên mới bởi tác nhân người dùng yêu cầu, máy chủ gốc có thể tạo tài nguyên với URI đó. "

Đó là, PUT đã từng tạo hoặc cập nhật.

Vì vậy, cái nào nên được sử dụng để tạo tài nguyên? Hay người ta cần hỗ trợ cả hai?


4468
2018-03-10 14:25


gốc


Có thể hữu ích khi sử dụng các định nghĩa trong HTTPbis - Roy đặt một số lượng công việc hợp lý vào việc làm rõ chúng. Xem: tools.ietf.org/html/… - Mark Nottingham
Chỉ cần đưa nhận xét của @ MarkNottingham về bản sửa đổi mới nhất, đây là BÀI ĐĂNG và ĐẶT, như được định nghĩa trên HTTPbis. - Marius Butuc
Dường như với tôi rằng cuộc tranh luận này đã nảy sinh từ thực tiễn phổ biến của việc đơn giản hóa REST bằng cách mô tả các phương thức HTTP về các hoạt động CRUD. - Stuporman
Không may là câu trả lời đầu tiên sai về POST. Kiểm tra câu trả lời của tôi để có giải thích rõ hơn về sự khác biệt: stackoverflow.com/a/18243587/2458234 - 7hi4g0
PUT và POST là cả hai phương pháp không an toàn. Tuy nhiên, PUT là idempotent, trong khi POST thì không. - Xem thêm tại: restcookbook.com/HTTP%20Methods/put-vs-post/… - Dinesh Saini


Các câu trả lời:


Nhìn chung: 

Cả PUT và POST đều có thể được sử dụng để tạo.

Bạn phải hỏi "bạn đang thực hiện hành động gì?" để phân biệt những gì bạn nên sử dụng. Giả sử bạn đang thiết kế một API để đặt câu hỏi. Nếu bạn muốn sử dụng POST thì bạn sẽ làm điều đó với một danh sách các câu hỏi. Nếu bạn muốn sử dụng PUT thì bạn sẽ làm điều đó với một câu hỏi cụ thể.

Tuyệt vời cả hai có thể được sử dụng, vì vậy cái nào tôi nên sử dụng trong thiết kế RESTful của tôi:

Bạn không cần hỗ trợ cả PUT và POST.

Được sử dụng là trái với bạn. Nhưng chỉ cần nhớ sử dụng đúng tùy thuộc vào đối tượng bạn đang tham chiếu trong yêu cầu.

Một số cân nhắc:

  • Bạn có đặt tên cho các đối tượng URL mà bạn tạo một cách rõ ràng hoặc để máy chủ quyết định không? Nếu bạn đặt tên cho chúng thì hãy sử dụng PUT. Nếu bạn để máy chủ quyết định thì hãy sử dụng POST.
  • PUT là idempotent, vì vậy nếu bạn PUT một đối tượng hai lần, nó không có hiệu lực. Đây là một tài sản tốt, vì vậy tôi sẽ sử dụng PUT khi có thể.
  • Bạn có thể cập nhật hoặc tạo tài nguyên bằng PUT với cùng một URL đối tượng
  • Với POST, bạn có thể có 2 yêu cầu đến cùng lúc để thực hiện sửa đổi cho URL và chúng có thể cập nhật các phần khác nhau của đối tượng.

Một ví dụ:

Tôi đã viết như sau một phần của câu trả lời khác về SO liên quan đến điều này:

BÀI ĐĂNG:

Được sử dụng để sửa đổi và cập nhật tài nguyên

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

Lưu ý rằng sau đây là một lỗi:

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

Nếu URL chưa được tạo, bạn   không nên sử dụng POST để tạo   trong khi chỉ định tên. Cái này nên   dẫn đến lỗi 'không tìm thấy tài nguyên'   bởi vì <new_question> không tồn tại   chưa. Bạn nên PUT <new_question>   tài nguyên trên máy chủ trước.

Bạn có thể làm một cái gì đó như   điều này để tạo tài nguyên bằng POST:

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

Lưu ý rằng trong trường hợp này, tài nguyên   tên không được chỉ định, các đối tượng mới   Đường dẫn URL sẽ được trả lại cho bạn.

ĐẶT: 

Được sử dụng để tạo tài nguyên hoặc   ghi đè lên nó. Trong khi bạn chỉ định   tài nguyên URL mới.

Đối với tài nguyên mới:

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

Để ghi đè tài nguyên hiện tại:

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

3487
2018-03-10 14:29



Tôi nghĩ người ta không thể nhấn mạnh sự thật rằng PUT là idempotent: nếu mạng bị hỏng và khách hàng không chắc chắn liệu yêu cầu của mình có thực hiện được hay không, nó chỉ có thể gửi nó lần thứ hai (hoặc thứ 100), và nó được đảm bảo bởi HTTP spec rằng điều này có tác dụng chính xác giống như gửi một lần. - Jörg W Mittag
@ Jörg W Mittag: Không cần thiết. Lần thứ hai có thể trả lại 409 Xung đột hoặc một cái gì đó nếu yêu cầu đã được sửa đổi trong khi chờ đợi (bởi một số người dùng khác hoặc yêu cầu đầu tiên của chính nó, đã trải qua). - Mitar
Nếu tôi không nhầm, điều chúng ta nên nhấn mạnh là PUT là xác định để được idempotent. Bạn vẫn phải viết máy chủ của bạn theo cách mà PUT hoạt động chính xác, đúng không? Có lẽ tốt hơn nên nói "PUT khiến cho việc vận chuyển giả định tính không tải, có thể ảnh hưởng đến hành vi của việc vận chuyển, ví dụ: bộ nhớ đệm." - Ian Ni-Lewis
@ JörgWMittag Idempotence khẩu hiệu? Làm thế nào về "Gửi và gửi và gửi cho bạn bè của tôi, nó làm cho không có sự khác biệt cuối cùng." - James Beninger
Hãy nghĩ về chúng như: PUT = chèn hoặc cập nhật; POST = chèn. Vì vậy, khi bạn thực hiện hai PUT - bạn sẽ có được một kỷ lục mới, khi bạn làm hai POST - bạn sẽ có được hai bản ghi mới. - Eugen Konkov


Bạn có thể tìm thấy các xác nhận trên web có nội dung

Không hoàn toàn đúng.


Tốt hơn là chọn giữa PUT và POST dựa trên NULL của hành động.

ĐẶT ngụ ý đặt một tài nguyên - thay thế hoàn toàn mọi thứ có sẵn tại URL đã cho bằng một điều khác. Theo định nghĩa, một PUT là idempotent. Làm điều đó nhiều lần tùy thích, và kết quả là như nhau. x=5 là idempotent. Bạn có thể PUT một tài nguyên cho dù nó có tồn tại trước đó hay không (ví dụ: Tạo, hoặc Cập nhật)!

BÀI ĐĂNG cập nhật tài nguyên, thêm tài nguyên công ty con hoặc gây ra thay đổi. BÀI ĐĂNG không phải là không đáng tin cậy, theo cách mà x++ không phải là idempotent.


Bởi đối số này, PUT là để tạo ra khi bạn biết URL của điều bạn sẽ tạo ra. POST có thể được sử dụng để tạo khi bạn biết URL của "nhà máy" hoặc người quản lý cho danh mục những thứ bạn muốn tạo.

vì thế:

POST /expense-report

hoặc là:

PUT  /expense-report/10929

1882
2018-04-22 14:55



Tôi đồng ý, bất cứ nơi nào idempotence là có liên quan nó nên trump bất kỳ mối quan tâm khác kể từ khi nhận được rằng sai có thể gây ra nhiều lỗi bất ngờ nhiều. - Josh
Nếu POST có thể cập nhật một tài nguyên, làm thế nào mà không phải là idempotent? Nếu tôi thay đổi độ tuổi của học sinh bằng PUT và làm điều đó gấp 10 lần tuổi của học sinh thì tương tự nếu tôi làm điều đó một lần. - Schneider
@Schneider, trong trường hợp này máy chủ của bạn đang nỗ lực thêm để đảm bảo tính không đáng tin cậy, nhưng nó không quảng cáo nó. Trình duyệt sẽ vẫn cảnh báo người dùng nếu họ cố gắng tải lại yêu cầu POST như vậy. - Tobu
@Schneider POST có thể tạo tài nguyên công ty con; do đó bạn có thể POST lên bộ sưu tập, như POST / báo cáo chi phí và nó sẽ tạo ra nhiều thực thể (báo cáo chi phí) trên máy chủ của bạn như số lượng yêu cầu bạn đã gửi, ngay cả khi chúng hoàn toàn giống nhau. Hãy suy nghĩ về nó như chèn cùng một hàng trong bảng DB (/ chi phí-báo cáo) với khóa chính tăng tự động. Dữ liệu vẫn giữ nguyên, khóa (URI trong trường hợp này) được tạo ra bởi máy chủ và khác nhau cho mỗi lần chèn khác (yêu cầu). Vì vậy, hiệu ứng POST có thể là không đáng kể, nhưng cũng có thể không phải. Do đó, POST là không phải idempotent. - Snifff
Giả sử chúng ta có các thực thể có thể có hai thuộc tính - name và date. Nếu chúng ta có một thực thể với một name và date, nhưng sau đó đưa ra yêu cầu cho nó chỉ xác định name, hành vi thích hợp của ĐẶT sẽ xóa bỏ date của thực thể, trong khi BÀI ĐĂNG chỉ có thể cập nhật các thuộc tính được chỉ định, để lại các thuộc tính không xác định như trước khi yêu cầu được thực hiện. Điều đó có đúng âm thanh / hợp lý hay không, sử dụng không đúng cách ĐẶT (Tôi thấy các tham chiếu đến VÁ, có vẻ như nó sẽ phù hợp hơn, nhưng vẫn chưa tồn tại)? - Jon z


  • BÀI ĐĂNG vào một URL tạo một nguồn tài nguyên con tại một máy chủ được xác định URL.
  • ĐẶT vào một URL tạo / thay thế tài nguyên toàn bộ tại khách hàng được xác định URL.
  •  vào một URL cập nhật phần của tài nguyên tại URL được khách hàng xác định đó.

Thông số kỹ thuật có liên quan cho PUT và POST là RFC 2616 §9,5ff.

POST tạo tài nguyên con, để POST /items tạo ra một nguồn tài nguyên sống dưới /items nguồn. Ví dụ. /items/1. Việc gửi cùng một gói bài đăng hai lần sẽ tạo ra hai tài nguyên.

ĐẶT là để tạo hoặc thay thế tài nguyên tại URL được khách hàng biết đến.

Vì thế: ĐẶT chỉ là một ứng cử viên cho CREATE nơi máy khách đã biết url trước khi tài nguyên được tạo. Ví dụ. /blogs/nigel/entry/when_to_use_post_vs_put vì tiêu đề được sử dụng làm khóa tài nguyên

ĐẶT thay thế tài nguyên tại url đã biết nếu nó đã tồn tại, vì vậy việc gửi cùng một yêu cầu hai lần sẽ không có hiệu lực. Nói cách khác, cuộc gọi tới PUT là không đáng kể.

RFC đọc như sau:

Sự khác biệt cơ bản giữa các yêu cầu POST và PUT được phản ánh theo ý nghĩa khác nhau của Request-URI. URI trong yêu cầu POST xác định tài nguyên sẽ xử lý thực thể được đính kèm. Tài nguyên đó có thể là một quá trình chấp nhận dữ liệu, một cổng vào một số giao thức khác hoặc một thực thể riêng biệt chấp nhận các chú thích. Ngược lại, URI trong một yêu cầu PUT xác định thực thể kèm theo yêu cầu - tác nhân người dùng biết URI là gì và máy chủ PHẢI KHÔNG cố gắng áp dụng yêu cầu cho một số tài nguyên khác. Nếu máy chủ mong muốn yêu cầu được áp dụng cho một URI khác,

Chú thích: PUT chủ yếu được sử dụng để cập nhật các tài nguyên (bằng cách thay thế chúng trong toàn bộ chúng), nhưng gần đây có chuyển động hướng tới việc sử dụng PATCH để cập nhật các tài nguyên hiện có, như PUT xác định rằng nó thay thế toàn bộ tài nguyên. RFC 5789.


563
2018-04-07 05:52



Hoặc từ phía bên kia của hàng rào: PUT nếu máy khách xác định địa chỉ của tài nguyên kết quả, POST nếu máy chủ thực hiện nó. - DanMan
Tôi nghĩ rằng câu trả lời này nên được chỉnh sửa để làm cho nó rõ ràng hơn những gì @DanMan chỉ một cách rất đơn giản. Những gì tôi thấy có giá trị nhất ở đây là lưu ý ở cuối, nói rằng một PUT chỉ nên được sử dụng để thay thế toàn bộ tài nguyên. - Hermes
PATCH không phải là một lựa chọn thực tế trong ít nhất một vài năm, nhưng tôi đồng ý với ý thức hệ. - crush
Tôi đang cố gắng để hiểu, nhưng bằng cách sử dụng PUT để tạo ra một cái gì đó sẽ chỉ có ý nghĩa nếu khách hàng biết chắc chắn rằng các nguồn tài nguyên không tồn tại được nêu ra, phải không? Theo ví dụ trên blog, giả sử bạn đã tạo hàng trăm bài đăng trên blog trong một vài năm, sau đó vô tình chọn cùng một tiêu đề như bạn đã làm cho bài đăng hai năm trước. Bây giờ bạn đã đi và thay thế bài đăng đó, không được dự định. Vì vậy, sử dụng PUT để tạo ra sẽ yêu cầu khách hàng theo dõi những gì được thực hiện và những gì không, và có thể dẫn đến tai nạn và tác dụng phụ ngoài ý muốn, cũng như có các tuyến đường làm hai điều hoàn toàn khác nhau? - galaxyAbstractor
Bạn nói đúng. Đưa ra một bài đăng trên blog tại cùng một url như một bài đăng hiện có sẽ gây ra một bản cập nhật cho bài đăng hiện có đó (mặc dù bạn rõ ràng có thể kiểm tra trước bằng GET). Điều này cho thấy tại sao ý tưởng xấu là chỉ sử dụng tiêu đề làm URL. Tuy nhiên nó sẽ làm việc ở bất cứ nơi nào có một khóa tự nhiên trong dữ liệu ... mà trong kinh nghiệm của tôi là hiếm. Hoặc nếu bạn đã sử dụng GUID - Nigel Thorne


Tóm lược:

Tạo nên:

Có thể được thực hiện với cả PUT hoặc POST theo cách sau:

ĐẶT

Tạo CÁC tài nguyên mới với newResourceId làm số nhận dạng, trong URI / resources hoặc bộ sưu tập.

PUT /resources/<newResourceId> HTTP/1.1 

BÀI ĐĂNG

Tạo A tài nguyên mới trong URI / resources, hoặc bộ sưu tập. Thông thường, số nhận dạng được trả về bởi máy chủ.

POST /resources HTTP/1.1

Cập nhật:

Có thể chỉ có được thực hiện với PUT theo cách sau:

ĐẶT

Cập nhật tài nguyên với existingResourceId làm số nhận dạng, trong URI / resources hoặc bộ sưu tập.

PUT /resources/<existingResourceId> HTTP/1.1

Giải trình:

Khi giao dịch với REST và URI là chung, bạn có chung trên trái và riêng trên đúng. Các generics thường được gọi là bộ sưu tập và hơn thế nữa riêng các mặt hàng có thể được gọi là nguồn. Lưu ý rằng nguồn có thể chứa bộ sưu tập.

Ví dụ:

<- chung - cụ thể ->

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

Khi bạn sử dụng POST, bạn luôn luôn đề cập đến một bộ sưu tập, vì vậy bất cứ khi nào bạn nói:

POST /users HTTP/1.1

bạn đang đăng một người dùng mới lên người dùng  bộ sưu tập.

Nếu bạn tiếp tục và thử một cái gì đó như thế này:

POST /users/john HTTP/1.1

nó sẽ hoạt động, nhưng về mặt ngữ nghĩa bạn đang nói rằng bạn muốn thêm một tài nguyên vào John  bộ sưu tập Bên dưới người dùng  bộ sưu tập.

Khi bạn đang sử dụng PUT, bạn đang đề cập đến nguồn hoặc một vật phẩm, có thể bên trong một bộ sưu tập. Vì vậy, khi bạn nói:

PUT /users/john HTTP/1.1

bạn đang nói với bản cập nhật máy chủ, hoặc tạo ra nếu nó không tồn tại, John  nguồn Bên dưới người dùng  bộ sưu tập.

Spec:

Hãy để tôi làm nổi bật một số phần quan trọng của thông số:

BÀI ĐĂNG

Các BÀI ĐĂNG phương thức được sử dụng để yêu cầu máy chủ gốc Chấp nhận thực thể được bao gồm trong yêu cầu dưới dạng Mới cấp dưới của tài nguyên được xác định bởi Yêu cầu-URI trong Dòng yêu cầu

Do đó, tạo mới nguồn trên một bộ sưu tập.

ĐẶT

Các ĐẶT phương thức yêu cầu thực thể đính kèm được lưu trữ theo Yêu cầu-URI. Nếu URI yêu cầu đề cập đến đã tồn tại tài nguyên, thực thể kín được NÊN được coi là phiên bản được sửa đổi của người cư trú trên máy chủ gốc. Nếu Request-URI thực hiện không trỏ đến hiện tại tài nguyên và URI đó là có khả năng được định nghĩa là Mới nguồn bởi tác nhân người dùng yêu cầu, máy chủ gốc có thể tạo nên tài nguyên với URI đó. "

Do đó, tạo hoặc cập nhật dựa trên sự tồn tại của nguồn.

Tài liệu tham khảo:


164
2017-08-14 22:47



Bài đăng này hữu ích cho tôi khi biết rằng POST thêm "cái gì đó" như một đứa trẻ vào bộ sưu tập đã cho (URI), trong khi PUT xác định rõ ràng "cái gì đó" tại vị trí URI đã cho. - kwah
Đây là câu trả lời hay nhất, ở đây, tôi nghĩ: không ai trong số này "POST có thể cập nhật một tài nguyên" vô nghĩa. Tôi thích tuyên bố của bạn, "Cập nhật chỉ có thể được thực hiện với PUT". - Thomas
Không, PUT không phải là để cập nhật hoặc tạo. Nó là để thay thế. Lưu ý rằng bạn có thể thay thế không có gì với hiệu ứng tạo ra. - thecoshman
@ 7hi4g0 PUT là để cập nhật với một sự thay thế hoàn toàn, nói cách khác, nó thay thế. Bạn không thay thế được gì với thứ gì đó, hoặc thứ gì đó với một cái gì đó hoàn toàn mới. PUT không phải là để thực hiện một thay đổi nhỏ (trừ khi bạn có khách hàng thực hiện thay đổi nhỏ và cung cấp toàn bộ phiên bản mới, ngay cả những gì còn lại như cũ). Đối với sửa đổi một phần, PATCH là phương pháp lựa chọn. - thecoshman
@thecoshman Bạn có thể, nhưng nó sẽ không được quá rõ ràng rằng tạo ra cũng được bảo hiểm trong đó. Trong trường hợp này, nó là tốt hơn để được rõ ràng. - 7hi4g0


Tôi muốn thêm lời khuyên "thực dụng" của tôi. Sử dụng PUT khi bạn biết "id" mà đối tượng bạn đang lưu có thể được truy xuất. Sử dụng PUT sẽ không hoạt động tốt nếu bạn cần, giả sử, một cơ sở dữ liệu được tạo ra sẽ được trả về cho bạn để thực hiện tra cứu hoặc cập nhật trong tương lai.

Vì vậy: Để lưu một người dùng hiện có hoặc một nơi mà khách hàng tạo id và nó đã được xác minh rằng id là duy nhất:

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

Nếu không, hãy sử dụng POST để tạo đối tượng ban đầu và PUT để cập nhật đối tượng:

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

155
2018-01-15 19:59



Trên thực tế, nó phải là POST /users. (Lưu ý rằng /users là số nhiều.) Điều này có ảnh hưởng đến việc tạo người dùng mới và biến nó thành tài nguyên con của /users bộ sưu tập. - DavidRR
@DavidRR là công bằng, làm thế nào để xử lý các nhóm là một cuộc tranh luận hoàn toàn. GET /users có ý nghĩa, nó đọc như bạn muốn, nhưng tôi sẽ ổn với GET /user/<id> hoặc là POST /user (với tải trọng cho người dùng mới nói) bởi vì nó đọc chính xác 'làm cho tôi người dùng 5' là lẻ, nhưng 'làm cho tôi người dùng 5' là tự nhiên hơn. Tôi có lẽ vẫn còn rơi xuống ở phía bên của pluralisation mặc dù :) - thecoshman


POST có nghĩa là "tạo mới" như trong "Đây là đầu vào để tạo người dùng, tạo nó cho tôi".

PUT có nghĩa là "chèn, thay thế nếu đã tồn tại" như trong "Đây là dữ liệu cho người dùng 5".

Bạn POST tới example.com/users vì bạn chưa biết URL của người dùng, bạn muốn máy chủ tạo nó.

Bạn PUT thành example.com/users/id vì bạn muốn thay thế / tạo riêng người dùng.

Đăng hai lần với cùng một dữ liệu có nghĩa là tạo hai người dùng giống hệt nhau với các id khác nhau. PUTing hai lần với cùng một dữ liệu tạo ra người dùng đầu tiên và cập nhật anh ta vào cùng một trạng thái lần thứ hai (không có thay đổi). Kể từ khi bạn kết thúc với cùng một tiểu bang sau một PUT không có vấn đề bao nhiêu lần bạn thực hiện nó, nó được cho là "đều mạnh" mỗi lần - idempotent. Điều này hữu ích cho việc tự động thử lại các yêu cầu. Không còn 'bạn có chắc chắn muốn gửi lại' khi bạn nhấn nút quay lại trên trình duyệt hay không.

Một lời khuyên chung là sử dụng POST khi bạn cần máy chủ kiểm soát việc tạo URL tài nguyên của bạn. Sử dụng PUT nếu không. Thích PUT hơn POST.


144
2017-10-23 14:27



Sloppiness có thể làm cho nó được thường được dạy rằng chỉ có hai động từ bạn cần: GET và POST. GET để có được, POST để thay đổi. Ngay cả PUT và DELETE được thực hiện bằng POST. Hỏi PUT thực sự có nghĩa là 25 năm sau đó có thể là một dấu hiệu chúng tôi đã học được nó sai lúc đầu. REST phổ biến đã đưa mọi người trở lại những điều cơ bản mà bây giờ chúng ta phải bỏ qua những sai lầm xấu. POST đã bị lạm dụng và bây giờ thường được dạy không chính xác. Phần tốt nhất: "Đăng hai lần với cùng một dữ liệu có nghĩa là tạo hai [tài nguyên] giống hệt nhau". Điểm tuyệt vời! - maxpolk
Làm thế nào bạn có thể sử dụng PUT để tạo một bản ghi bằng ID, như trong ví dụ của bạn user 5 nếu nó chưa tồn tại? Bạn không có ý update, replace if already exists? hay gì đó - Luke
@Coulton: Tôi có nghĩa là những gì tôi đã viết. Bạn chèn người dùng 5 nếu bạn PUT đến / users / 5 và # 5 chưa tồn tại. - Alexander Torstling
@Coulton: Và PUT cũng có thể được sử dụng để thay thế giá trị của một hiện tại toàn bộ tài nguyên. - DavidRR
"Thích PUT hơn POST" ... quan tâm để biện minh cho điều đó? - thecoshman


Sử dụng POST để tạo và PUT để cập nhật. Đó là cách Ruby on Rails đang làm điều đó, dù sao đi nữa.

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

104
2018-03-10 14:28



POST /items thêm một mục mới vào một tài nguyên đã được xác định ('mục'). Nó không, như câu trả lời nói, "tạo một nhóm." Tôi không hiểu tại sao điều này có 12 phiếu. - David J.
Ra khỏi hộp, Rails không hỗ trợ 'tạo nhóm' thông qua REST. Để 'tạo một nhóm' theo đó tôi có nghĩa là 'tạo một tài nguyên', bạn phải làm điều đó thông qua mã nguồn. - David J.
Đây là một hướng dẫn công bằng, nhưng là một sự đơn giản. Như các câu trả lời khác đề cập đến, một trong hai phương pháp có thể được sử dụng cho cả tạo và cập nhật. - Brad Koch
Tôi đồng ý với câu trả lời với một sửa đổi nhỏ. Sử dụng POST để tạo và PUT để cập nhật tài nguyên hoàn toàn. Đối với các bản cập nhật một phần, chúng tôi có thể sử dụng PUT hoặc PATCH. Cho phép nói rằng chúng tôi muốn cập nhật trạng thái của một nhóm. Chúng tôi có thể sử dụng PUT / nhóm / 1 / trạng thái với trạng thái là trọng tải yêu cầu hoặc PATCH / groups / 1 với các chi tiết về hành động trong tải trọng - java_geek
Nó cũng nên được làm rõ rằng PUT /items/42 cũng hợp lệ cho đang tạo một nguồn tài nguyên, nhưng chỉ khi khách hàng có đặc quyền đặt tên tài nguyên. (Rails có cho phép một khách hàng đặc quyền đặt tên này không?) - DavidRR


REST là một rất khái niệm cấp cao. Trong thực tế, nó thậm chí không đề cập đến HTTP ở tất cả!

Nếu bạn có bất kỳ nghi ngờ nào về cách triển khai REST trong HTTP, bạn luôn có thể xem Giao thức xuất bản Atom (AtomPub) đặc điểm kỹ thuật. AtomPub là một tiêu chuẩn để viết các dịch vụ web RESTful với HTTP được phát triển bởi nhiều ánh sáng HTTP và REST, với một số đầu vào từ Roy Fielding, nhà phát minh của REST và (đồng sáng lập) của chính HTTP.

Trong thực tế, bạn thậm chí có thể sử dụng AtomPub trực tiếp. Trong khi nó ra khỏi cộng đồng viết blog, nó không bị giới hạn viết blog: nó là một giao thức chung cho việc tương tác RESTful với các bộ sưu tập tùy ý (lồng nhau) tùy ý thông qua HTTP. Nếu bạn có thể đại diện cho ứng dụng của mình như một tập hợp các tài nguyên, bạn có thể sử dụng AtomPub và không phải lo lắng về việc sử dụng PUT hay POST, các mã trạng thái HTTP nào sẽ trả về và tất cả các chi tiết đó.

Đây là những gì AtomPub đã nói về việc tạo tài nguyên (phần 9.2):

Để thêm thành viên vào Bộ sưu tập, khách hàng gửi yêu cầu POST tới URI của Bộ sưu tập.


57
2018-03-10 15:27



Không có gì sai khi cho phép PUT tạo tài nguyên. Chỉ cần lưu ý rằng nó có nghĩa là khách hàng cung cấp URL. - Julian Reschke
Có điều gì đó rất sai khi cho phép PUT tạo tài nguyên: khách hàng cung cấp URL. Đó là công việc của máy chủ! - Joshcodes
@Joshcodes Nó không phải luôn luôn là trường hợp đó là công việc của máy chủ để tạo id khách hàng. Tôi đã ngày càng nhìn thấy các thiết kế cho phép khách hàng tạo ra một số loại UUID làm id tài nguyên. Thiết kế này cho vay đặc biệt để tăng quy mô. - Justin Ohms
@JustinOhms Tôi đồng ý với quan điểm của bạn về ID khách hàng tạo ra (lưu ý phụ: tất cả các hệ thống do tôi thiết kế kể từ khoảng năm 2008 yêu cầu khách hàng tạo ID là UUID / Hướng dẫn). Điều đó không có nghĩa là khách hàng nên chỉ định URL. - Joshcodes
@Joshcodes Đó là vấn đề tách mối quan tâm. Nơi URL được tạo ra thực sự là hậu quả rất ít. Có máy chủ chịu trách nhiệm phân phối nội dung từ URL chính xác nhưng điều đó không giới hạn máy chủ phản hồi yêu cầu trên URL không chính xác. Câu trả lời chính xác từ máy chủ trong trường hợp này là 308. Một khách hàng thích hợp sẽ thử lại PUT trên URL chính xác. Một ví dụ khác là một hệ thống phân tán mà không phải tất cả các nút đều biết về tất cả các tài nguyên được cung cấp bởi các máy khách. Ở đây một PUT để tạo sẽ hoàn toàn hợp lệ bởi vì đối với nút máy chủ đó, tài nguyên không tồn tại. - Justin Ohms