Khi đưa ra yêu cầu XÓA HTTP, URI yêu cầu phải xác định hoàn toàn tài nguyên cần xóa. Tuy nhiên, có được phép thêm dữ liệu meta bổ sung như một phần của cơ thể thực thể của yêu cầu không?
Khi đưa ra yêu cầu XÓA HTTP, URI yêu cầu phải xác định hoàn toàn tài nguyên cần xóa. Tuy nhiên, có được phép thêm dữ liệu meta bổ sung như một phần của cơ thể thực thể của yêu cầu không?
Câu trả lời:
Thông số kỹ thuật không rõ ràng cấm hoặc không khuyến khích nó, vì vậy tôi có xu hướng nói rằng nó được cho phép.
Microsoft nhìn nhận nó theo cùng một cách (tôi có thể nghe thấy tiếng thì thầm trong khán giả), họ nêu trong bài viết của MSDN về Phương pháp XÓA của Khung dịch vụ dữ liệu ADO.NET :
Nếu một yêu cầu XÓA bao gồm một cơ thể thực thể, cơ thể đó sẽ bị bỏ qua [...]
Ngoài ra, đây là những gì RFC2616 (HTTP 1.1) nói về các yêu cầu:
Content-Length
hoặc Transfer-Encoding
tiêu đề (phần 4.3)Đối với câu trả lời, điều này đã được xác định:
Bản cập nhật mới nhất cho đặc tả HTTP 1.1 ( RFC 7231 ) cho phép rõ ràng cho phép một cơ thể thực thể trong một yêu cầu XÓA:
Một tải trọng trong một thông báo yêu cầu XÓA không có ngữ nghĩa được xác định; gửi phần thân tải trọng theo yêu cầu XÓA có thể khiến một số triển khai hiện có từ chối yêu cầu.
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
Vì vậy, nó đi kèm với một cảnh báo tương thích ngược, nó gợi ý rằng tiêu chuẩn tiếp theo sẽ nói: 'vâng! DELETE
có thể có một cơ thể`.
A payload within a DELETE request message has no defined semantics
. Vì vậy, cơ thể được cho phép.
Một số phiên bản của Tomcat và Jetty dường như bỏ qua một cơ thể thực thể nếu nó có mặt. Điều này có thể gây phiền toái nếu bạn có ý định nhận nó.
Một lý do để sử dụng phần thân trong yêu cầu xóa là để kiểm soát đồng thời lạc quan.
Bạn đọc phiên bản 1 của một bản ghi.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Đồng nghiệp của bạn đọc phiên bản 1 của hồ sơ.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Đồng nghiệp của bạn thay đổi bản ghi và cập nhật cơ sở dữ liệu, cập nhật phiên bản thành 2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Bạn cố gắng xóa hồ sơ:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
Bạn sẽ có được một ngoại lệ khóa lạc quan. Đọc lại hồ sơ, thấy rằng nó quan trọng và có thể không xóa nó.
Một lý do khác để sử dụng nó là xóa nhiều bản ghi cùng một lúc (ví dụ: lưới có các hộp kiểm chọn hàng).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Lưu ý rằng mỗi tin nhắn có phiên bản riêng. Có thể bạn có thể chỉ định nhiều phiên bản bằng nhiều tiêu đề, nhưng theo George, việc này đơn giản và thuận tiện hơn nhiều.
Điều này hoạt động trong Tomcat (7.0.52) và Spring MVC (4.05), có thể cả các phiên bản trước đó nữa:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
hay Etag
, đó là những gì họ đang cho).
Dường như RFC 2616 không chỉ rõ điều này.
Từ phần 4.3:
Sự hiện diện của phần thân thông báo trong yêu cầu được báo hiệu bằng cách bao gồm trường tiêu đề Độ dài nội dung hoặc chuyển mã hóa nội dung trong tiêu đề thư của yêu cầu. Phần thân thông báo KHÔNG được đưa vào yêu cầu nếu đặc tả của phương thức yêu cầu (phần 5.1.1) không cho phép gửi phần thân thực thể trong các yêu cầu. Một máy chủ NÊN đọc và chuyển tiếp nội dung thư theo bất kỳ yêu cầu nào; nếu phương thức yêu cầu không bao gồm ngữ nghĩa được xác định cho một thực thể, thì phần thân thông báo NÊN bị bỏ qua khi xử lý yêu cầu.
Và phần 9.7:
Phương thức DELETE yêu cầu máy chủ gốc xóa tài nguyên được xác định bởi URI yêu cầu. Phương pháp này CÓ THỂ bị ghi đè bởi sự can thiệp của con người (hoặc các phương tiện khác) trên máy chủ gốc. Máy khách không thể được đảm bảo rằng thao tác đã được thực hiện, ngay cả khi mã trạng thái được trả về từ máy chủ gốc cho biết rằng hành động đã được hoàn thành thành công. Tuy nhiên, máy chủ KHÔNG NÊN chỉ ra thành công trừ khi tại thời điểm phản hồi được đưa ra, nó dự định xóa tài nguyên hoặc di chuyển nó đến một vị trí không thể truy cập.
Phản hồi thành công NÊN 200 (OK) nếu phản hồi bao gồm một thực thể mô tả trạng thái, 202 (Được chấp nhận) nếu hành động chưa được ban hành hoặc 204 (Không có nội dung) nếu hành động đã được ban hành nhưng phản hồi không bao gồm một thực thể.
Nếu yêu cầu chuyển qua bộ đệm và URI yêu cầu xác định một hoặc nhiều thực thể hiện được lưu trong bộ nhớ cache, các mục đó NÊN được coi là cũ. Phản hồi cho phương pháp này không được lưu trữ.
Vì vậy, nó không được phép hoặc không được phép rõ ràng và có khả năng một proxy trên đường đi có thể xóa nội dung thư (mặc dù nó NÊN đọc và chuyển tiếp nó).
Chỉ cần đề phòng, nếu bạn cung cấp phần thân trong yêu cầu XÓA của mình và đang sử dụng bộ cân bằng tải HTTPS trên đám mây của Google, nó sẽ từ chối yêu cầu của bạn với lỗi 400. Tôi đã đập đầu vào tường và phát hiện ra rằng Google, vì bất kỳ lý do gì, cho rằng một yêu cầu XÓA với một cơ thể là một yêu cầu không đúng.
for whatever reason
- bởi vì thông số kỹ thuật nói như vậy: P
DELETE
là sau.
Có vẻ như ElasticSearch sử dụng điều này: https://www.elastic.co/guide/en/elaticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Có nghĩa là Netty hỗ trợ này.
Giống như được đề cập trong các ý kiến, nó có thể không còn là trường hợp nữa
Roy Fielding trong danh sách gửi thư HTTP làm rõ rằng trong danh sách gửi thư http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html và nói:
Cơ thể NHẬN / XÓA hoàn toàn bị cấm có bất kỳ tác động nào đến việc xử lý hoặc giải thích yêu cầu
Điều này có nghĩa là cơ thể không được sửa đổi hành vi của máy chủ. Sau đó, ông nói thêm:
ngoài sự cần thiết phải đọc và loại bỏ các byte nhận được để duy trì việc đóng khung thư.
Và cuối cùng là lý do không cấm cơ thể:
Lý do duy nhất chúng tôi không cấm gửi một cơ thể là vì điều đó sẽ dẫn đến việc thực hiện lười biếng với giả định không có cơ thể nào được gửi.
Vì vậy, trong khi khách hàng có thể gửi thân tải trọng, máy chủ nên bỏ nó và API không nên xác định ngữ nghĩa cho thân tải trọng theo các yêu cầu đó.
Điều này không được xác định .
Một tải trọng trong một thông báo yêu cầu XÓA không có ngữ nghĩa được xác định; gửi một cơ thể tải trọng theo yêu cầu XÓA có thể khiến một số triển khai hiện có từ chối yêu cầu.
https://tools.ietf.org/html/rfc7231#page-29
Sử dụng XÓA với một cơ thể là rủi ro ... Tôi thích cách tiếp cận này cho Danh sách hoạt động hơn REST:
Hoạt động thường xuyên
NHẬN / đối tượng / Nhận tất cả các đối tượng
GET / object / ID Nhận một đối tượng với ID được chỉ định
POST / object Thêm một đối tượng mới
PUT / object / ID Thêm một đối tượng với ID được chỉ định, cập nhật một đối tượng
XÓA / đối tượng / ID Xóa đối tượng với ID được chỉ định
Tất cả các hành động tùy chỉnh là POST
POST / object / addList Thêm Danh sách hoặc Mảng đối tượng có trong phần thân
POST / object / xóaList Xóa một danh sách các đối tượng có trong phần thân
POST / object / customQuery Tạo Danh sách dựa trên truy vấn tùy chỉnh trong phần thân
Nếu khách hàng không hỗ trợ các hoạt động mở rộng của bạn, họ có thể làm việc theo cách thông thường.
POST
không phải là cách RESTy tốt để tạo tài nguyên mới vì ngữ nghĩa của phản hồi POST không rõ ràng, đặc biệt là trong ngữ cảnh của các tiêu đề Vị trí. Về cơ bản, bạn để lại HTTP và xếp RPC lên trên. Các hợp "HTTP / REST cách" là tạo ra nguồn lực sử dụng PUT
w / các If-None-Match: *
tiêu đề (hoặc spec'ing phương thức HTTP thích hợp, xem MKCOL
vv).
Tôi không nghĩ rằng một câu trả lời tốt cho điều này đã được đăng, mặc dù đã có rất nhiều bình luận tuyệt vời về câu trả lời hiện có. Tôi sẽ nâng ý chính của những bình luận đó thành một câu trả lời mới:
Đoạn này từ RFC7231 đã được trích dẫn một vài lần, trong đó tổng hợp nó.
Một tải trọng trong một thông báo yêu cầu XÓA không có ngữ nghĩa được xác định; gửi phần thân tải trọng theo yêu cầu XÓA có thể khiến một số triển khai hiện có từ chối yêu cầu.
Điều tôi bỏ lỡ từ các câu trả lời khác là hàm ý. Vâng, nó được phép bao gồm một cơ thể theo DELETE
yêu cầu, nhưng nó vô nghĩa về mặt ngữ nghĩa. Điều này thực sự có nghĩa là việc ban hành mộtDELETE
yêu cầu với một cơ quan yêu cầu tương đương về mặt ngữ nghĩa với việc không bao gồm một cơ quan yêu cầu.
Bao gồm một cơ thể yêu cầu sẽ không có bất kỳ ảnh hưởng nào đến yêu cầu, vì vậy không bao giờ có một điểm trong đó bao gồm nó.
tl; dr: Về mặt kỹ thuật, một DELETE
yêu cầu với cơ thể yêu cầu được cho phép, nhưng nó không bao giờ hữu ích để làm như vậy.
Trong trường hợp bất cứ ai đang chạy vào thử nghiệm vấn đề này, Không, nó không được hỗ trợ phổ biến.
Tôi hiện đang thử nghiệm với Sahi Pro và rất rõ ràng một cuộc gọi http XÓA bất kỳ dữ liệu cơ thể nào được cung cấp (một danh sách lớn các id để xóa hàng loạt theo thiết kế điểm cuối).
Tôi đã liên lạc với họ nhiều lần cũng như gửi trong ba gói kịch bản, hình ảnh, nhật ký riêng biệt để họ xem xét và họ vẫn chưa xác nhận điều này. Một bản vá thất bại, và một cuộc gọi hội nghị bị bỏ lỡ bởi sự hỗ trợ của họ sau đó và tôi vẫn chưa nhận được câu trả lời chắc chắn.
Tôi chắc chắn Sahi không hỗ trợ điều này và tôi sẽ tưởng tượng nhiều công cụ khác đi theo bộ.
Có thể url GitHUb dưới đây sẽ giúp bạn, để có câu trả lời. Trên thực tế, Máy chủ ứng dụng như Tomcat, Weblogic từ chối cuộc gọi HTTP.DELETE với tải trọng yêu cầu. Vì vậy, hãy ghi nhớ tất cả những điều này, tôi đã thêm ví dụ trong github, xin vui lòng xem xét điều đó