Xóa tài nguyên bằng http DELETE


123

Vì vậy, cho rằng động từ DELETE trong Http là không có ý nghĩa, khi tôi đưa ra yêu cầu sau, điều gì sẽ xảy ra ở lần thứ hai (hoặc thứ ba, hoặc thứ tư, v.v.)?

DELETE /person/123

Lần đầu tiên, tài nguyên bị xóa và tôi trả về 204 (thành công, không có nội dung). Tôi nên trả lại số 204 trong các cuộc gọi tiếp theo hay số 404 (không tìm thấy)?

Câu trả lời:


153

Vì các yêu cầu HTTP trong một hệ thống không trạng thái phải độc lập, kết quả của một yêu cầu không được phụ thuộc vào yêu cầu trước đó. Hãy xem xét điều gì sẽ xảy ra nếu hai người dùng thực hiện XÓA trên cùng một tài nguyên đồng thời. Yêu cầu thứ hai nhận được 404. Điều này cũng đúng nếu một người dùng thực hiện hai yêu cầu.

Tôi đoán rằng việc DELETE trả về hai câu trả lời khác nhau không cảm thấy hữu ích cho bạn. Tôi thấy hữu ích khi nghĩ về các yêu cầu Idempotent là để hệ thống ở cùng một trạng thái, không nhất thiết phải có cùng một phản hồi. Vì vậy, bất kể bạn XÓA tài nguyên hiện có hay cố gắng XÓA tài nguyên không tồn tại, trạng thái tài nguyên máy chủ đều giống nhau.


4
Cảm ơn bạn. Nghe có lý! Tôi đã thực sự nghĩ về Idempotent là trả lại cùng một phản hồi.
Craig Wilson

4
@Craig Cẩn thận! Trong Cookbook, Subbu hoàn toàn trái ngược với những gì tôi vừa nói. Ông nói rằng tính đơn giản có nghĩa là nó sẽ trả lại cùng một phản hồi. May mắn thay, Subbu sẽ tham dự RESTFest nên tôi sẽ nói rõ với anh ấy ở đó.
Darrel Miller

57
Nếu bạn XÓA thứ gì đó không tồn tại, bạn chỉ nên trả về 204 (ngay cả khi tài nguyên chưa bao giờ tồn tại). Khách hàng muốn tài nguyên biến mất và nó đã biến mất. Trả lại 404 đang để lộ quá trình xử lý nội bộ không quan trọng đối với máy khách và sẽ dẫn đến tình trạng lỗi không cần thiết.
Brian

9
@DarrelMiller Tôi đoán khái niệm chính ở đây là bạn không nên sử dụng DELETE để kiểm tra xem tài nguyên có tồn tại hay không, trước tiên bạn nên sử dụng GET cho điều đó. Sau đó, nếu phản hồi là 200, bạn sẽ thực hiện XÓA; nếu không thì thậm chí không cần làm điều đó. Vì vậy, tôi nghĩ việc luôn trả về 204 trên DELETE là rất hợp lý.
manei_cc

10
@Brian RFC nói rằng nó phải hoạt động như thế nào rm. rmtrả về lỗi nếu nó không tồn tại. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl 22/09/17

32

Sách dạy nấu ăn của các dịch vụ web RESTful là một nguồn tài liệu tuyệt vời cho việc này. Tình cờ, bản xem trước trên google của nó hiển thị trang về DELETE (trang 11):

Phương thức DELETE là không quan trọng. Điều này ngụ ý rằng máy chủ phải trả về mã phản hồi 200 (OK) ngay cả khi máy chủ đã xóa tài nguyên trong một yêu cầu trước đó. Nhưng trên thực tế, việc triển khai DELETE như một hoạt động không cần thiết yêu cầu máy chủ phải theo dõi tất cả các tài nguyên đã xóa. Nếu không, nó có thể trả về 404 (Không tìm thấy).


Vâng, đó có vẻ như là một nguồn tài nguyên tuyệt vời. Tuy nhiên, phần XÓA không phù hợp với tôi (nó nằm ở trang 23 và bản xem trước đã bị biên tập lại). Bạn đã đọc cuốn sách này? Bạn có tình cờ biết câu trả lời cho câu hỏi của tôi không?
Craig Wilson

Cuốn sách này phải có để xây dựng REST (nó nói cụ thể, không phải bằng ngôn ngữ).
yves amsellem

7
@Craig Đọc Sách dạy nấu ăn, nó nói rằng bạn NÊN trả lại 200 OK ngay cả khi bạn đã xóa nó rồi. Tuy nhiên, trong thực tế mà sẽ yêu cầu máy chủ để theo dõi tất cả các nguồn lực xóa, do đó, bạn có thể dùng 404. Nó đi vào để nói rằng vấn đề an ninh có thể yêu cầu bạn phải luôn luôn trả 404. Trang 11.
Darrel Miller

+1 Thứ hai và rất đề xuất cuốn sách thiết kế các dịch vụ RESTful.
Paul DelRe

18
Chà, cuốn sách đã sai. Idempotency không ngụ ý rằng mã trạng thái sẽ giống nhau. Những gì có liên quan là trạng thái cuối cùng của máy chủ.
Julian Reschke

13

Tôi đồng ý với những gì câu trả lời được chọn hiện tại đã nói, rằng DELETE thứ 2 (và thứ 3, thứ 4, ...) sẽ nhận được 404 . Và, tôi nhận thấy rằng câu trả lời có 143 lượt bình chọn nhưng cũng có một bình luận ngược lại có 54 lượt bình chọn trở lên, vì vậy cộng đồng được chia thành 2 phe theo tỷ lệ khoảng 3: 1. Ở đây có thêm thông tin để giải quyết cuộc tranh luận lâu dài này.

  1. Trước hết, chúng ta hãy KHÔNG bắt đầu với những gì "tôi" nghĩ, những gì "bạn" nghĩ, hoặc những gì một tác giả cuốn sách khác nghĩ. Hãy bắt đầu với thông số kỹ thuật HTTP, tức là RFC 7231.

    • RFC 7231, phần 4.3.5 DELETE đã xảy ra để chỉ đề cập đến một phản hồi thành công phải là 2xx, nhưng nó không gọi ra một DELETE tiếp theo sẽ nhận được gì. Vì vậy, chúng ta hãy tìm hiểu sâu hơn.
    • RFC 7231, mục 6.5.4 404 Không tìm thấy cho biết phản hồi 404 dành cho tài nguyên không tồn tại. Vì không có phương thức http cụ thể nào (đặc biệt, không phải là DELETE) được gọi ra để được xử lý theo cách khác, chúng tôi có thể trực quan nhận được một lần hiển thị (và đúng như vậy), yêu cầu của tôi DELETE /some/resource/which/does/not/existsẽ dẫn đến 404. Sau đó, DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agocũng có thể trả về 404 Sau đó, tại sao phải DELETE /some/resource/i/deleted/five/seconds/agokhác nhau? "Nhưng làm thế nào về tính đơn giản ?!", tôi có thể nghe thấy bạn đang hét lên rằng. Chờ đã, chúng tôi sắp đi vào vấn đề đó.
    • Trong lịch sử, RFC 2616, được xuất bản vào năm 1999, là thông số kỹ thuật HTTP 1.1 được tham chiếu nhiều nhất. Thật không may, mô tả của nó về tính đơn giản rất mơ hồ , điều đó dành chỗ cho tất cả các cuộc tranh luận này. Nhưng thông số kỹ thuật đó đã được thay thế bởi RFC 7231. Trích dẫn từ RFC 7231, phần 4.2.2 Phương pháp Idempotent , tôi nhấn mạnh:

      Một phương thức yêu cầu được coi là "idempotent" nếu TÁC DỤNG dự kiến ​​TRÊN MÁY CHỦ của nhiều yêu cầu giống hệt nhau với phương thức đó giống như hiệu ứng đối với một yêu cầu như vậy. Trong số các phương thức yêu cầu được xác định bởi đặc tả này, PUT, DELETE và các phương thức yêu cầu an toàn là không quan trọng .

      Vì vậy, nó được viết trong thông số kỹ thuật, tính đơn giản là tất cả về hiệu ứng trên máy chủ. DELETE đầu tiên trả về 204 và sau đó DELETE tiếp theo trả về 404, mã trạng thái khác nhau như vậy KHÔNG làm cho DELETE không phải là ý tưởng. Sử dụng đối số này để biện minh cho lần trả lại 204 tiếp theo, đơn giản là không thích hợp.

  2. OK vì vậy nó không phải là về tính đơn giản. Nhưng sau đó một câu hỏi tiếp theo có thể là, nếu chúng ta vẫn chọn sử dụng 204 trong XÓA tiếp theo thì sao? Là nó ổn?

    Câu hỏi hay. Động cơ có thể hiểu được: cho phép khách hàng vẫn đạt được kết quả dự kiến ​​mà không cần lo lắng về việc xử lý lỗi. Tôi sẽ nói rằng, trả về 204 trong DELETE tiếp theo, là một "lời nói dối trắng" phía máy chủ phần lớn là vô hại, mà phía máy khách sẽ không nhận ra sự khác biệt ngay lập tức. Đó là lý do tại sao có ~ 25% người làm điều đó trong tự nhiên và nó dường như vẫn hoạt động. Chỉ cần lưu ý rằng, lời nói dối như vậy có thể được coi là kỳ lạ về mặt ngữ nghĩa, bởi vì GET /non-existtrả về 404 nhưng DELETE /non-existlại cho 204, tại thời điểm đó khách hàng sẽ nhận ra dịch vụ của bạn không hoàn toàn tuân thủ phần 6.5.4 404 Not Found .

    Nhưng tôi muốn chỉ ra rằng, cách dự định được gợi ý bởi RFC 7231, tức là trả về 404 trong lần DELETE tiếp theo, không phải là một vấn đề ngay từ đầu. Có gấp 3 lần nhà phát triển chọn làm điều đó và bạn đã bao giờ nghe thấy một sự cố lớn hoặc phàn nàn do khách hàng không thể xử lý 404 chưa? Có lẽ, không, và đó là bởi vì, bất kỳ ứng dụng khách tốt nào triển khai HTTP DELETE (hoặc bất kỳ phương thức HTTP nào, cho vấn đề đó), sẽ không mù quáng cho rằng kết quả sẽ luôn là thành công 2xx. Và sau đó, khi nhà phát triển bắt đầu xem xét việc xử lý lỗi, 404 Not Found sẽ là một trong những lỗi đầu tiên xuất hiện trong tâm trí. Tại thời điểm đó, anh ấy / cô ấy có thể sẽ rút ra kết luận rằng, hoạt động HTTP DELETE bỏ qua lỗi 404 là an toàn về mặt ngữ nghĩa. Và họ đã làm như vậy.

Vấn đề đã được giải quyết.


2
+1 "tính đơn giản là tất cả về hiệu ứng trên máy chủ". Trả lời một cách tỉ mỉ. Làm tốt! Tôi là người tin tưởng 404 cho các yêu cầu XÓA tiếp theo.
nwayve

11

XÓA đầu tiên : 200 hoặc 204.

Điểm XÓA Tiếp theo : 200 hoặc 204.

Cơ sở lý luận : DELETE phải là không quan trọng. Nếu bạn quay trở lại 404 trên DELETE thứ hai, phản ứng của bạn đang thay đổi từ một đang thành công với một mã lỗi . Chương trình khách hàng có thể thực hiện các hành động không chính xác dựa trên giả định việc XÓA không thành công.

Ví dụ :

  • Giả sử hoạt động DELETE của bạn là một phần của hoạt động nhiều bước (hoặc "saga") được thực thi bởi chương trình khách hàng.
  • Ví dụ: chương trình khách hàng có thể là một ứng dụng di động thực hiện giao dịch ngân hàng.
  • Giả sử chương trình khách hàng có tự động thử lại thao tác DELETE (điều đó hợp lý, vì DELETE được cho là không cần thiết).
  • Giả sử DELETE đầu tiên đã được thực thi thành công, nhưng phản hồi 200 bị mất trên đường đến chương trình khách.
  • Chương trình khách hàng sẽ thử lại việc XÓA.
  • Nếu lần thử thứ hai trả về 404, chương trình khách hàng có thể hủy hoạt động tổng thể vì mã lỗi này.
  • Nhưng bởi vì lần DELETE đầu tiên được thực thi thành công trên máy chủ, hệ thống có thể ở trạng thái không nhất quán .
  • Nếu lần thử thứ hai trả về 200 hoặc 204, chương trình khách hàng sẽ tiến hành như mong đợi.

Chỉ để minh họa việc sử dụng phương pháp này, hướng dẫn kiểu API HTTP cho PayPal có hướng dẫn sau:

DELETE: Phương thức này NÊN trả về mã trạng thái 204 vì không cần trả lại bất kỳ nội dung nào trong hầu hết các trường hợp vì yêu cầu xóa tài nguyên và nó đã được xóa thành công.

Vì phương thức DELETE cũng PHẢI là idmpotent, nên nó vẫn NÊN trả về 204, ngay cả khi tài nguyên đã bị xóa. Thông thường, người tiêu dùng API không quan tâm xem tài nguyên đã bị xóa như một phần của hoạt động này hay trước đó. Đây cũng là lý do tại sao 204 thay vì 404 nên được trả về.


1
Câu hỏi là, điều gì quan trọng đối với máy khách, đã xóa tài nguyên hay tài nguyên đó đã bị xóa. Điều gì sẽ xảy ra nếu một số khách hàng khác xóa tài nguyên trong saga. Bạn có thực sự muốn thất bại khi xem xét mục tiêu khách hàng đã đạt được?
Darrel Miller

1
@DarrelMiller Điểm tốt. Điều gì quan trọng hơn phụ thuộc vào bối cảnh kinh doanh. Nhưng nói chung, tôi muốn trả lại 204 trong lần thử XÓA thứ hai, ngay cả khi tài nguyên đã bị xóa bởi ứng dụng khách khác. Tôi không muốn dịch vụ bị lỗi (tức là 404) vì đã đạt được mục tiêu khách hàng.
Paulo Merson

2
Như những người khác đã đề cập, tính đơn giản không phải là mã phản hồi của bạn, nó là trạng thái máy chủ của bạn.
Niranjan

@Niranjan Tôi đồng ý rằng tính đơn giản là về trạng thái máy chủ, nhưng mã phản hồi khác có thể khiến máy khách thay đổi trạng thái máy chủ một cách không cần thiết bằng cách hủy một câu chuyện đang diễn ra.
Paulo Merson

@Paulo Merson bạn sẽ trả lại mã nào nếu khách hàng yêu cầu xóa một mục KHÔNG BAO GIỜ tồn tại? 204? hoặc 404? Nếu bạn luôn trả về 204 mã trả lại thì ích gì?
frenchone 21/09/18
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.