Là một cơ quan thực thể được phép cho một yêu cầu XÓA HTTP?


717

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?


4
Trong ASP.NET WebApi 2 FromBody Paramameter bị bỏ qua cho các endppoint của httpDelete.
Jenny O'Reilly

2
Tôi có một mối quan tâm tương tự, nhưng trường hợp của tôi là khác nhau. Tôi muốn đưa ra một yêu cầu xóa hàng loạt khi tôi muốn xóa hàng trăm đối tượng. Chắc chắn đó là một sự tăng cường hiệu suất tuyệt vời cho các mạng HTTP 2.0 trước.
Singagirl

1
Có bất kỳ thay đổi nào trong HTTP / 2 không?
Jyotman Singh

Câu trả lời:


570

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:

  • một cơ thể thực thể chỉ hiện diện khi có một cơ thể thông điệp (phần 7.2)
  • sự hiện diện của phần thân thông điệp được báo hiệu bằng cách bao gồm một Content-Lengthhoặc Transfer-Encodingtiêu đề (phần 4.3)
  • một thông điệp cơ thể không được bao gồm khi các đặc điểm kỹ thuật của phương thức yêu cầu không cho phép gửi một thực thể cơ thể (phần 4.3)
  • một cơ thể thực thể chỉ bị cấm rõ ràng trong các yêu cầu TRACE, tất cả các loại yêu cầu khác không bị hạn chế (cụ thể là phần 9 và 9,8)

Đối với câu trả lời, điều này đã được xác định:

  • có bao gồm phần thân thông báo hay không phụ thuộc vào cả phương thức yêu cầu trạng thái phản hồi (phần 4.3)
  • một nội dung thư bị cấm rõ ràng trong các phản hồi đối với các yêu cầu CHÍNH (cụ thể là phần 9 và 9,4)
  • một nội dung thư bị cấm rõ ràng trong các phản hồi 1xx (thông tin), 204 (không có nội dung) và 304 (không sửa đổi) (phần 4.3)
  • tất cả các phản hồi khác bao gồm phần thân thông điệp, mặc dù nó có thể có độ dài bằng không (phần 4.3)

7
@Jason Chắc chắn. Bạn cũng có thể sử dụng các tiêu đề tùy chỉnh để truyền dữ liệu bổ sung, nhưng tại sao không sử dụng phần thân yêu cầu.
Tomalak

86
Mặc dù thông số kỹ thuật không cấm các yêu cầu XÓA có phần thân thông điệp, phần 4.3 dường như chỉ ra rằng phần thân nên bị các máy chủ bỏ qua vì không có "ngữ nghĩa được xác định" cho các phần tử thực thể XÓA : "Một máy chủ NÊN đọc và chuyển tiếp phần thân thông điệp 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 phần thân thực thể, thì phần thân thông điệp NÊN bị bỏ qua khi xử lý yêu cầu . "
shelley

72
Xin lưu ý rằng rất nhiều khách hàng cũng không thể gửi XÓA với một cơ thể. Điều này chỉ đốt cháy tôi trên Android.
Karmic Coder

1
@KarmicCoder: Điểm tuyệt vời. Thông tin thêm: Gửi yêu cầu XÓA HTTP trong Android .
MS Dousti

2
Rất nhiều cuộc thảo luận về việc thực hiện trộn lẫn với thông số HTTP. Khách hàng sẽ thực hiện mọi thứ theo cách họ diễn giải thông số kỹ thuật, đừng nhầm lẫn điều này với ý nghĩa của thông số kỹ thuật. Thực tế là thông số kỹ thuật để lại điều này mơ hồ. Tôi không đồng ý với giải thích rằng vì không có ngữ nghĩa được xác định cho cơ thể thực thể mà có một hàm ý rằng nó nên được bỏ qua. Tôi nghĩ mọi người đang làm việc ngược từ các diễn giải cụ thể của khách hàng tồn tại (Jersey, máy khách thử nghiệm Android, v.v.) và cố gắng biện minh cho việc giải thích thay vì cố gắng đúng với thông số kỹ thuật. Con người dễ sai lầm.
Gibron

169

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.


3
phiên bản mới nhất chưa được phê duyệt của thông số kỹ thuật loại bỏ yêu cầu này. Phiên bản mới nhất được phê duyệt vẫn là RFC2616 được trích dẫn ở trên.
Đức cha

4
Phiên bản nào? Phiên bản 20 vẫn có từ ngữ giống như phiên bản 19 mà tôi đã liên kết ở trên: "Các cơ quan về yêu cầu XÓA không có ngữ nghĩa được xác định. Lưu ý rằng việc gửi một nội dung 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."
nắm bắt

11
Các đề xuất phiên bản 26 mà bạn có thể cho phép một cơ thể: 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! DELETEcó thể có một cơ thể`.
Pure.Krom

4
RFC 7231 phần 4.3.5 hoàn thiện ngôn ngữ từ phiên bản 26 với A payload within a DELETE request message has no defined semantics. Vì vậy, cơ thể được cho phép.
mndrix

6
Cơ thể được cho phép nhưng không nên liên quan đến yêu cầu. Hoàn toàn không có điểm nào trong việc sử dụng nó.
Evert


50

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;
    }
}

15
Có các phần tử trong GET (và XÓA) rõ ràng đang ngược đãi HTTP và REST. Có các cơ chế khác để xử lý kiểm soát tương tranh (ví dụ: If-Modified-Because và etags).
Bruno

19
Làm thế nào nó rõ ràng ngược đãi nó khi thông số kỹ thuật không cấm cơ thể trong XÓA?
Neil McGuigan

5
Bởi vì bạn không có ý định làm bất cứ điều gì với cơ thể. Xem: stackoverflow.com/a/983458/372643
Bruno

14
Đây chính xác là cùng một vấn đề: GET cho phép bạn truy xuất đại diện của tài nguyên được xác định bởi URI và XÓA xóa tài nguyên được xác định bởi URI. Sử dụng URI khác cho các phiên bản khác nếu bạn muốn xóa các phiên bản cụ thể. URI phải là định danh duy nhất của tài nguyên trong HTTP / REST. Sử dụng siêu dữ liệu trong tiêu đề nếu bạn cần làm xử lý đồng thời (ví dụ If-Unmodified-Sincehay Etag, đó là những gì họ đang cho).
Bruno

5
Sử dụng tiêu đề ETag thay vì trường phiên bản trong cơ thể
malhal

26

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ó).


19

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.


1
for whatever reason- bởi vì thông số kỹ thuật nói như vậy: P
Mardoxx

20
Thông số kỹ thuật không "nói như vậy" nó chỉ nói rằng cơ thể không được xác định cụ thể. Nếu nó không được xác định và bạn muốn bỏ qua nó, tuyệt ... hãy tiếp tục và bỏ qua nó. Nhưng từ chối yêu cầu hoàn toàn có vẻ cực đoan và không cần thiết.
Ben Fried

1
Đừng dựa vào hành vi không xác định. Đó là một thực hành tốt nhất khá phổ biến.
Evert

@Evert có hành vi không xác định rõ ràng (chẳng hạn như bạn thấy mô tả trong thông số kỹ thuật của ngôn ngữ C chẳng hạn) và có hành vi được phép nhưng đơn giản là không được mô tả. Sử dụng một cơ thể tin nhắn trong DELETElà sau.
Alnitak

9

Điều đáng chú ý là đặc tả OpenAPI cho phiên bản 3.0 đã bỏ hỗ trợ cho các phương thức XÓA với phần thân:

xem ở đâyở đây để tham khảo

Điều này có thể ảnh hưởng đến việc triển khai, tài liệu hoặc sử dụng các API này trong tương lai.


7

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


1
Nếu bạn sử dụng apache http client, bạn có thể dễ dàng tạo các phiên bản GET và DELETE của riêng mình bằng cách mở rộng HttpEntityEnclosesRequestBase và làm cho phương thức getMethod () trả về GET hoặc DELETE. Chúng tôi sử dụng điều này để nói chuyện với elaticsearch.
Jilles van Gurp

2
liên kết chết - tuyệt vời. chúng tôi cần nhiều hơn những câu trả lời liên kết đó - không phải
Cottage

3
Tài liệu được liên kết hiện chỉ chứa các yêu cầu POST, không có XÓA. Có thể đáng để thêm một ghi chú cho câu trả lời này?
dshepherd

Elaticsearch sử dụng cơ thể với các yêu cầu GET quá.
Nidhin David

7

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 đó.


5

Đ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



3
Trích dẫn chính xác này đã được bao gồm trong các câu trả lời trước, câu trả lời này nên được xóa.
Madbreaks

5

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.


Sử dụng a POSTkhô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 PUTw / các If-None-Match: *tiêu đề (hoặc spec'ing phương thức HTTP thích hợp, xem MKCOLvv).
hnh

4

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 DELETEyê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 DELETEyê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.


2
"vô nghĩa về mặt ngữ nghĩa" không có nghĩa giống như "không có ngữ nghĩa xác định". Điều này có nghĩa là nó không thể có bất kỳ ý nghĩa. Cái sau đơn giản có nghĩa là bản thân RFC không chỉ định những ngữ nghĩa đó có thể là gì. (Tôi viết RFC)
Alnitak

1
Nói cách khác, nếu người triển khai API mong muốn tự xác định một số ngữ nghĩa, thì họ hoàn toàn tự do làm điều đó.
Alnitak

1
@Alnitak đây chắc chắn là một cách hiểu sai. Theo định nghĩa đó, bất kỳ phần yêu cầu HTTP nào cũng không có ngữ nghĩa được xác định, nhưng XÓA và GET được gọi cụ thể trong đặc tả. Dưới đây là một đoạn trích từ một bản thảo chưa-to-be-xuất bản nói về vấn đề này cụ thể về các yêu cầu GET:
Evert

1
Tôi không đồng ý với bạn rằng điều này không rõ ràng trong RFC hiện đang được phát hành, nhưng nếu bạn không tin tôi, tôi sẽ mời bạn hỏi các tác giả sau khi họ có ý định XÓA và NHẬN. Bạn sẽ thấy rằng nó phù hợp với câu trả lời của tôi. Giống như bạn, tôi cũng tham gia vào các cơ quan tiêu chuẩn và tôi không chỉ là một người đơn độc với ý kiến ​​về cách giải thích RFC.
Evert

2
Nếu đó là trường hợp thì 7231 được nói kém, và nên nói "cơ thể tải trọng PHẢI bị bỏ qua". Dự thảo nào bạn đang đề cập ở trên?
Alnitak

3

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ộ.


Nó được thực hiện trong phiên bản mới nhất của Sahi Pro. Do Sahi sử dụng java để thực hiện các cuộc gọi HTTP và Java đã gặp lỗi trước phiên bản 1.8, điều này sẽ không cho phép người dùng thực hiện yêu cầu XÓA. Vì vậy, với Java 1.8 trở đi và Sahi Pro 6.1.1 (sẽ sớm được công khai), mọi người có thể thực hiện yêu cầu XÓA với cơ thể ở Sahi.
Vivek V Dwivingi

-1

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 đó

https://github.com/ashish720/spring-examples


-1

Tôi đã có thể thực hiện thao tác XÓA với phần thân Yêu cầu. Tôi đã sử dụng cổng AWS Lambda và AWS API và sử dụng ngôn ngữ Go.


3
Họ đang nói về tiêu chuẩn, không phải khả năng. Bạn thậm chí có thể có một yêu cầu GET với cơ thể, điều này không tốt
ReZa
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.