Nếu một hoạt động 'PUT' RESTful trả lại một cái gì đó


437

Tôi đã tự hỏi ý kiến ​​của mọi người về PUThoạt động RESTful không trả về gì (null) trong phần phản hồi.

Câu trả lời:


613

Đặc tả HTTP ( RFC 2616 ) có một số khuyến nghị có thể áp dụng. Đây là cách giải thích của tôi:

  • Mã trạng thái HTTP 200 OKcho PUT thành công của bản cập nhật cho tài nguyên hiện có. Không có cơ thể đáp ứng cần thiết. (Theo Mục 9.6 , 204 No Contentthậm chí còn phù hợp hơn.)
  • Mã trạng thái HTTP 201 Createdcho PUT thành công của tài nguyên mới, với URI cụ thể nhất cho tài nguyên mới được trả về trong trường tiêu đề Vị trí và mọi URI và siêu dữ liệu có liên quan khác của tài nguyên được lặp lại trong phần phản hồi. ( RFC 2616 Mục 10.2.2 )
  • Mã trạng thái HTTP 409 Conflictcho PUT không thành công do sửa đổi lần thứ 3 , với một danh sách các khác biệt giữa bản cập nhật đã thử và tài nguyên hiện tại trong phần phản hồi. ( RFC 2616 Mục 10.4.10 )
  • Mã trạng thái HTTP 400 Bad Requestcho PUT không thành công, với văn bản ngôn ngữ tự nhiên (như tiếng Anh) trong phần phản hồi giải thích lý do tại sao PUT thất bại. ( RFC 2616 Mục 10.4 )

25
@stian Thú vị! Điều đó có vẻ khá tự phụ đối với Mozilla, vì tôi không thể tìm thấy gì trong RFC 2616 (đáng chú ý là các phần 10.2 thành công 2xx10.2.1 200 OK ) loại trừ việc sử dụng 200PUT, DELETE hoặc bất kỳ phương pháp nào khác. Tôi đã bỏ lỡ một cái gì đó? Chẳng hạn như Mozilla trở thành ông chủ của W3 và IETF? ;) Hoặc có thể họ chưa bao giờ nghe nói về Nguyên tắc Mạnh mẽ của Postel.
hệ thống PAUSE

52
@stian: Câu đó đã bị xóa vào ngày 3 tháng 2 năm 2013. Có lẽ vì ai đó đã đọc về nó ở đây. ;) developer.mozilla.org/en-US/docs/HTTP/ từ
Christian Strempfer

6
Ngữ nghĩa của phương pháp PUT là bỏ qua bất kỳ trạng thái hiện tại nào của tài nguyên, do đó, trả lại xung đột 409 cho PUT không thành công do sửa đổi bên thứ 3 chỉ có ý nghĩa nếu yêu cầu có điều kiện.
Pedro Werneck

8
@systemPAUSE Câu trả lời hay. Một điểm nhỏ: nếu bạn sẽ không trả lại phần thân phản hồi cho một thao tác thành công, tôi sẽ đề nghị sử dụng riêng 204. Một số khách hàng (ví dụ jQuery Ajax) sẽ bị nghẹt thở nếu họ mong đợi một phản hồi có độ dài khác không nhưng không nhận được nó. Bạn có thể thấy một ví dụ về điều này trong câu hỏi này .
nick_w

3
Có thể RFC2616 đã được cập nhật kể từ khi điều này được trả lời. Không có nơi nào trong 9.6 được đề cập No response body neededliên quan đến 200. Trên thực tế, cơ quan phản hồi hoàn toàn không được đề cập liên quan đến PUT. Nó chỉ nêu rõIf an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
james

163

Trái ngược với hầu hết các câu trả lời ở đây, tôi thực sự nghĩ rằng PUT nên trả về tài nguyên được cập nhật (tất nhiên ngoài mã HTTP).

Lý do tại sao bạn muốn trả lại tài nguyên dưới dạng phản hồi cho hoạt động PUT là vì khi bạn gửi một đại diện tài nguyên đến máy chủ, máy chủ cũng có thể áp dụng một số xử lý cho tài nguyên này, vì vậy khách hàng muốn biết tài nguyên này như thế nào hình như sau khi yêu cầu hoàn thành (nếu không, nó sẽ phải đưa ra một yêu cầu GET khác).


3
"Máy chủ cũng có thể áp dụng một số xử lý cho tài nguyên này": Tôi mới cái này. Đó thực sự là RESTful?
Raedwald

22
@Raedwald chắc chắn là như vậy. REST không yêu cầu toàn bộ tài nguyên phải được cập nhật trên PUT, mặc dù nó thường được khuyến nghị. Ví dụ, một số trường có thể không có ý nghĩa cập nhật - ngày được tạo hoặc ngày sửa đổi cuối cùng, có lẽ không nên được đưa vào phần thân PUT, nhưng có thể sẽ bị thay đổi do kết quả của PUT. Điều đó đã được nói, tôi không đồng ý với LiorH rằng PUT sẽ dẫn đến việc trả lại tài nguyên; Tôi sẽ yêu cầu NHẬN sau PUT để có được tài nguyên cập nhật.
Randolpho

19
@Randolpho REST không yêu cầu toàn bộ tài nguyên phải được cập nhật trên PUT, đây có phải là trường hợp của BỆNH NHÂN không ?
Marco Ciambrone

14
@MarcoCiambrone Vâng, tôi đồng ý và tôi đọc lại nhận xét trước đó của mình. Tôi đã thay đổi giai điệu của mình trên REST và PUT - PUT phải luôn bình thường và không bao giờ được sử dụng để cập nhật một phần. POST là lựa chọn thay thế duy nhất trừ khi PATCH được hỗ trợ, trong trường hợp đó, PATCH có thể là một lựa chọn tốt. Tuy nhiên, PATCH là một động từ mới và có thể không được hỗ trợ bởi một số khung công tác phía máy chủ.
Randolpho

2
Câu trả lời đã được viết tốt trước rfc7231, nhưng phần 4.3.4 cho thấy rõ "Phương thức PUT yêu cầu trạng thái của tài nguyên đích được tạo hoặc thay thế bằng trạng thái được xác định bởi biểu diễn trong tải trọng thông báo yêu cầu"
aaaaaa

3

Tôi nghĩ rằng máy chủ có thể trả về nội dung để phản hồi lại PUT. Nếu bạn đang sử dụng định dạng phong bì phản hồi cho phép dữ liệu được tải xuống (chẳng hạn như định dạng được sử dụng bởi dữ liệu ember), thì bạn cũng có thể bao gồm các đối tượng khác có thể đã được sửa đổi thông qua kích hoạt cơ sở dữ liệu, v.v. (Dữ liệu được tải xuống rõ ràng để giảm # yêu cầu và đây có vẻ là một nơi tốt để tối ưu hóa.)

Nếu tôi chỉ chấp nhận PUT và không có gì để báo cáo lại, tôi sử dụng mã trạng thái 204 không có phần thân. Nếu tôi có điều gì đó để báo cáo, tôi sử dụng mã trạng thái 200 và bao gồm một phần thân.


2

Thông số HTTP / 1.1 (phần 9.6) thảo luận về mã phản hồi / lỗi thích hợp. Tuy nhiên, nó không giải quyết nội dung phản hồi.

Bạn mong đợi điều gì? Một mã phản hồi HTTP đơn giản (200, v.v.) có vẻ đơn giản và không rõ ràng đối với tôi.


Có, nhưng nếu bạn muốn kiểm tra xem dữ liệu được chèn vào db sau khi PUT hoặc POST thực sự đại diện cho dữ liệu thực sự bạn muốn. Sẽ tốt hơn nếu HTTP có thể gửi lại phần thân của phản hồi.
tnkh

1
@tnkh những gì bạn đề nghị là hết sức ý tưởng. Thực hiện cuộc gọi GET riêng sau khi cập nhật thành công để đạt được những gì bạn muốn. Để đảm bảo hiệu suất giới thiệu một lớp bộ nhớ đệm nếu bạn đang gặp vấn đề trong bộ phận này. Chúng ta không thể giải quyết những vấn đề này bằng cách giải quyết vấn đề logic 'mọi thứ đều ổn'. Đừng loay hoay với các nguyên tắc lập trình cơ bản và 'vững chắc' vốn là lẽ thường trong năm 2020. Đó là một sự ô nhục!
XDS

@XDS Tôi xác nhận phần đầu tiên của bạn về nhận xét. Nhưng không thể dừng lại để đảo mắt sau đó. Bình luận vui nhộn
tnkh

Cảm ơn về việc xây dựng lý do tại sao bạn thấy nó vui nhộn mặc dù.
XDS

2

Nếu phần cuối của API REST là cơ sở dữ liệu quan hệ SQL, thì

  1. bạn nên có RowVersion trong mọi bản ghi có thể được cập nhật (để tránh sự cố cập nhật bị mất )
  2. bạn phải luôn trả lại một bản sao mới của bản ghi sau PUT (để lấy RowVersion mới ).

Nếu bạn không quan tâm đến các cập nhật bị mất hoặc nếu bạn muốn buộc khách hàng của mình thực hiện NHẬN ngay sau khi PUT, thì đừng trả lại bất cứ điều gì từ PUT.


1

Mã phản hồi của năm 201 cho "Đã tạo" cùng với tiêu đề "Vị trí" để chỉ đến nơi khách hàng có thể tìm thấy tài nguyên mới được tạo.


5
Các đối tượng PUT không (hoặc không nên) tài nguyên mới được tạo
kdazzle

9
@kdazzle PUT chắc chắn có thể là một tài nguyên mới được tạo và thường là như vậy. w3.org/Prot Protocol / rfc2616 / rfc2616
Charlie Schliesser

3
Chỉ để giải thích nhận xét của tôi tốt hơn một chút. PUT có nghĩa là, đặt mặt hàng này tại vị trí cụ thể này, thay thế những gì hiện có (nếu có).
dùng1751825

3
Đúng, "thay thế những gì hiện có" là cụm từ chính. Nó đã tồn tại và nó đang được thay thế. PUT không nên để tạo tài nguyên mới.
Kevin M

3
@KevinM Như trong RFC doc rfc7231 mới nhất , nó nói rằng các tài nguyên có thể được tạo: "Phương thức PUT yêu cầu trạng thái của tài nguyên đích được tạo hoặc thay thế [...]" và lý do bạn nghĩ PUT không thể tạo tài nguyên mới là vì bạn không nhất thiết phải biết vị trí của tài nguyên mới. Nhưng nếu bạn biết vị trí / định danh của nó, nó có thể được tạo nếu nó chưa ở đó.
Leo Lei

0

Tôi đã sử dụng API RESTful trong các dịch vụ của mình và đây là ý kiến ​​của tôi: Đầu tiên chúng ta phải có một chế độ xem chung PUTđược sử dụng để cập nhật một tài nguyên không tạo hoặc nhận.

Tôi đã xác định tài nguyên với: Stateless resourceStateful resource:

  • Tài nguyên không trạng thái Đối với các tài nguyên này, chỉ cần trả lại Mã nguồn với phần thân trống, thế là đủ.

  • Tài nguyên trạng thái Ví dụ: phiên bản của tài nguyên. Đối với loại tài nguyên này, bạn phải cung cấp phiên bản khi bạn muốn thay đổi nó, vì vậy hãy trả lại toàn bộ tài nguyên hoặc trả lại phiên bản cho khách hàng, vì vậy khách hàng không cần gửi yêu cầu nhận sau hành động cập nhật.

Nhưng , đối với một dịch vụ hoặc hệ thống, giữ nósimple,clearly,easy to use and maintainlà điều quan trọng nhất.


6
"PUT được sử dụng để cập nhật tài nguyên không tạo hoặc nhận." - điều đó không đúng cũng không phổ biến. Theo thông số kỹ thuật, PUT có thể tạo tài nguyên. Xóa = theo thông số kỹ thuật thường được biết đến.
Imre Pühvel

-3

Giống như một cơ quan Yêu cầu trống phù hợp với mục đích ban đầu của yêu cầu GET và cơ quan phản hồi trống phù hợp với mục đích ban đầu của yêu cầu PUT.


-3

có vẻ ổn ... mặc dù tôi nghĩ rằng một dấu hiệu thô sơ về thành công / thất bại / thời gian được đăng / # byte nhận được / v.v. sẽ thích hợp hơn

chỉnh sửa: Tôi đã suy nghĩ theo dòng toàn vẹn dữ liệu và / hoặc lưu giữ hồ sơ; siêu dữ liệu như hàm băm MD5 hoặc dấu thời gian cho thời gian nhận được có thể hữu ích cho các tệp dữ liệu lớn.


1
Làm thế nào khoảng 200 OK trong tiêu đề phản hồi trạng thái? Bạn có nghĩ rằng đủ để nói, "Làm việc tốt cảm ơn?"
AnthonyWJones

tiêu đề phản hồi sẽ chứa mã trạng thái và vâng, chúng tôi đang nói về HTTP tại thời điểm này :)
AwoppyCoder

-4

Lý tưởng nhất là nó sẽ trả về một phản ứng thành công / thất bại.


13
Không phải trong cơ thể phản ứng, mặc dù. Mã trạng thái HTTP là nơi dành cho điều đó. Có lẽ nếu có lỗi, một số thông tin lỗi mở rộng có thể được trả lại trong giá thầu phản hồi
Archetypal Paul

-4

Có một sự khác biệt giữa tiêu đề và nội dung của phản hồi HTTP. PUT không bao giờ nên trả lại phần thân, nhưng phải trả về mã phản hồi trong tiêu đề. Chỉ cần chọn 200 nếu thành công và 4xx nếu không. Không có thứ gọi là mã trả về null. tại sao bạn muốn làm việc này?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.