เมื่อออกคำขอ HTTP DELETE URI คำขอควรระบุทรัพยากรที่จะลบอย่างสมบูรณ์ อย่างไรก็ตามอนุญาตให้เพิ่ม meta-data พิเศษเป็นส่วนหนึ่งของเอนทิตีของคำขอได้หรือไม่
เมื่อออกคำขอ HTTP DELETE URI คำขอควรระบุทรัพยากรที่จะลบอย่างสมบูรณ์ อย่างไรก็ตามอนุญาตให้เพิ่ม meta-data พิเศษเป็นส่วนหนึ่งของเอนทิตีของคำขอได้หรือไม่
คำตอบ:
สเป็คไม่ได้ห้ามหรือกีดกันอย่างชัดเจนดังนั้นฉันมักจะบอกว่ามันได้รับอนุญาต
Microsoft เห็นด้วยวิธีเดียวกัน (ฉันสามารถได้ยินเสียงพึมพำต่อผู้ชม) พวกเขาระบุไว้ในบทความ MSDN เกี่ยวกับวิธีการลบของ ADO.NET Data Services Framework :
หากคำขอ DELETE มีเนื้อหาขององค์กรเนื้อหาจะถูกละเว้น [... ]
นอกจากนี้นี่คือสิ่งที่RFC2616 (HTTP 1.1) ได้กล่าวเกี่ยวกับคำขอ:
Content-Length
หรือTransfer-Encoding
ส่วนหัว (ส่วน 4.3)สำหรับการตอบกลับสิ่งนี้ได้ถูกกำหนดไว้แล้ว:
การอัปเดตล่าสุดของข้อมูลจำเพาะ HTTP 1.1 ( RFC 7231 ) อนุญาตให้องค์กรอย่างชัดเจนในคำขอ DELETE:
เพย์โหลดภายในข้อความคำขอลบไม่มีความหมายที่กำหนดไว้ การส่งส่วนของส่วนของข้อมูลบนคำขอ DELETE อาจทำให้การใช้งานที่มีอยู่บางส่วนปฏิเสธคำขอ
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.
ดังนั้นจึงมาพร้อมกับคำเตือนความเข้ากันได้แบบย้อนหลังแนะนำว่ามาตรฐานถัดไปจะกล่าวว่า: 'อ๋อ! DELETE
สามารถมีร่างกายได้
A payload within a DELETE request message has no defined semantics
พร้อมด้วย ดังนั้นร่างกายจึงได้รับอนุญาต
Tomcat และ Jetty บางรุ่นดูเหมือนจะเพิกเฉยต่อเนื้อความเอนทิตีหากมีอยู่ ซึ่งอาจสร้างความรำคาญถ้าคุณตั้งใจจะรับมัน
เหตุผลหนึ่งที่ใช้เนื้อความในคำขอลบคือเพื่อการควบคุมภาวะพร้อมกันในแง่ดี
คุณอ่านระเบียน 1 รุ่น
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
เพื่อนร่วมงานของคุณอ่านเรคคอร์ดรุ่น 1
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
เพื่อนร่วมงานของคุณเปลี่ยนระเบียนและอัปเดตฐานข้อมูลซึ่งอัปเดตเวอร์ชันเป็น 2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
คุณพยายามที่จะลบบันทึก:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
คุณควรได้รับข้อยกเว้นการล็อคในแง่ดี อ่านบันทึกใหม่ดูว่าสำคัญและอาจไม่ลบ
อีกเหตุผลหนึ่งที่ใช้คือลบหลายระเบียนพร้อมกัน (ตัวอย่างเช่นกริดที่มีเช็กบ็อกซ์การเลือกแถว)
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
โปรดสังเกตว่าแต่ละข้อความมีเวอร์ชันของตัวเอง บางทีคุณสามารถระบุหลาย ๆ รุ่นโดยใช้หลายหัว แต่โดย George นี่ง่ายกว่าและสะดวกกว่ามาก
ใช้งานได้กับ Tomcat (7.0.52) และ Spring MVC (4.05) ซึ่งอาจเป็นเวอร์ชั่นก่อนหน้านี้เช่นกัน:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
หรือEtag
นั่นคือสิ่งที่พวกเขากำลังทำ)
สำหรับฉันแล้วดูเหมือนว่าRFC 2616ไม่ได้ระบุสิ่งนี้
จากส่วนที่ 4.3:
การปรากฏตัวของเนื้อความในคำขอมีการส่งสัญญาณโดยการรวมของส่วนหัวของเนื้อหาความยาวหรือการถ่ายโอนการเข้ารหัสในส่วนหัวของข้อความของคำขอ ต้องไม่รวมเนื้อหาของข้อความในคำขอหากข้อมูลจำเพาะของวิธีการร้องขอ (ส่วน 5.1.1) ไม่อนุญาตให้ส่งเนื้อหาขององค์กรในคำขอ เซิร์ฟเวอร์ควรอ่านและส่งต่อเนื้อความในการร้องขอใด ๆ ; หากวิธีการร้องขอไม่ได้รวมซีแมนทิกส์ที่กำหนดไว้สำหรับเอนทิตีเนื้อหาจากนั้นเนื้อหาของข้อความ SHOULD จะถูกละเว้นเมื่อจัดการคำขอ
และมาตรา 9.7:
เมธอด DELETE ร้องขอให้เซิร์ฟเวอร์ต้นทางลบทรัพยากรที่ระบุโดย Request-URI วิธีนี้อาจถูกแทนที่โดยการแทรกแซงของมนุษย์ (หรือวิธีอื่น ๆ ) บนเซิร์ฟเวอร์ต้นทาง ลูกค้าไม่สามารถรับประกันได้ว่าการดำเนินการได้ดำเนินการแม้ว่ารหัสสถานะที่ส่งคืนจากเซิร์ฟเวอร์ต้นทางบ่งชี้ว่าการดำเนินการเสร็จสมบูรณ์แล้ว อย่างไรก็ตามเซิร์ฟเวอร์ไม่ควรระบุความสำเร็จเว้นแต่ในเวลาที่มีการตอบสนองจะมีความตั้งใจที่จะลบทรัพยากรหรือย้ายไปยังตำแหน่งที่ไม่สามารถเข้าถึงได้
การตอบสนองที่ประสบความสำเร็จควรเป็น 200 (OK) หากการตอบสนองนั้นรวมถึงเอนทิตีที่อธิบายสถานะ 202 (ยอมรับแล้ว) หากการกระทำนั้นยังไม่ได้มีการประกาศใช้หรือ 204 (ไม่มีเนื้อหา) หากการกระทำนั้นมีการตราขึ้นแล้ว นิติบุคคล
หากการร้องขอผ่านแคชและ Request-URI ระบุเอนทิตีแคชในปัจจุบันอย่างน้อยหนึ่งรายการรายการเหล่านั้นควรถูกใช้เป็นค้าง การตอบสนองต่อวิธีนี้ไม่สามารถแคชได้
ดังนั้นจึงไม่ได้รับอนุญาตหรือไม่อนุญาตอย่างชัดเจนและมีโอกาสที่พร็อกซีตลอดทางอาจลบเนื้อหาของข้อความ (แม้ว่ามันควรจะอ่านและส่งต่อ)
เพียงแค่หัวขึ้นหากคุณจัดหาเนื้อหาในคำขอ DELETE ของคุณและกำลังใช้ตัวโหลดบาลานซ์ HTTPS ของ Google Cloud ก็จะปฏิเสธคำขอของคุณด้วยข้อผิดพลาด 400 ฉันต่อสู้กับกำแพงและพบว่า Google ไม่ว่าด้วยเหตุผลใดคิดว่าคำขอลบด้วยร่างกายเป็นคำขอที่มีรูปแบบไม่ถูกต้อง
for whatever reason
- เพราะสเป็คพูดอย่างนั้น: P
DELETE
เป็นสิ่งสุดท้าย
ดูเหมือนว่า ElasticSearch จะใช้สิ่งนี้: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
ซึ่งหมายความว่า Netty สนับสนุนสิ่งนี้
เช่นเดียวกับที่กล่าวถึงในความคิดเห็นอาจไม่เป็นเช่นนั้นอีกต่อไป
Roy Fielding ในรายการส่งเมล HTTP ชี้แจงว่าในรายการส่งเมล http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.htmlและพูดว่า:
GET / DELETE ห้ามมิให้มีผลกระทบใด ๆ ในการประมวลผลหรือตีความคำขอ
ซึ่งหมายความว่าร่างกายต้องไม่ปรับเปลี่ยนพฤติกรรมของเซิร์ฟเวอร์ จากนั้นเขาก็เพิ่ม:
นอกเหนือจากความจำเป็นในการอ่านและทิ้งไบต์ที่ได้รับเพื่อรักษากรอบข้อความ
และในที่สุดเหตุผลที่ไม่ห้ามไม่ให้มีร่างกาย:
เหตุผลเดียวที่เราไม่ห้ามการส่งศพคือเพราะจะนำไปสู่การใช้งานที่ขี้เกียจโดยไม่คิดว่าจะมีการส่งศพ
ดังนั้นในขณะที่ลูกค้าสามารถส่งส่วนของข้อมูลได้เซิร์ฟเวอร์ควรวางและ API ไม่ควรกำหนดความหมายสำหรับส่วนของข้อมูลในคำขอเหล่านั้น
นี้ไม่ได้กำหนดไว้
เพย์โหลดภายในข้อความคำขอลบไม่มีความหมายที่กำหนดไว้ การส่งส่วนของส่วนของข้อมูลบนคำขอ DELETE อาจทำให้การใช้งานที่มีอยู่บางส่วนปฏิเสธคำขอ
https://tools.ietf.org/html/rfc7231#page-29
การใช้ DELETE กับร่างกายมีความเสี่ยง ... ฉันชอบวิธีการนี้สำหรับการดำเนินการตามรายการมากกว่า REST
ปฏิบัติการปกติ
GET / วัตถุ / รับวัตถุทั้งหมด
GET / object / ID รับวัตถุที่มี ID ที่ระบุ
POST / objects เพิ่มวัตถุใหม่
วาง / object / ID เพิ่มวัตถุที่มี ID ที่ระบุปรับปรุงวัตถุ
DELETE / object / ID ลบวัตถุที่มี ID ที่ระบุ
การกระทำที่กำหนดเองทั้งหมดคือ POST
POST / objects / addList เพิ่มรายการหรืออาร์เรย์ของวัตถุที่รวมอยู่ในเนื้อหา
POST / objects / deleteList ลบรายชื่อของวัตถุที่รวมอยู่ในร่างกาย
POST / objects / customQuery สร้างรายการตามแบบสอบถามที่กำหนดเองในเนื้อหา
หากลูกค้าไม่สนับสนุนการดำเนินการเพิ่มเติมของคุณพวกเขาสามารถทำงานได้ตามปกติ
POST
ไม่ใช่วิธีที่ดีในการสร้างทรัพยากรใหม่เนื่องจากความหมายของการตอบกลับ POST ไม่ชัดเจนโดยเฉพาะอย่างยิ่งในบริบทของส่วนหัวสถานที่ตั้ง คุณต้องทิ้ง HTTP ไว้เบื้องหลังและสแต็ก RPC ไว้ด้านบน เหมาะสม "ทาง HTTP / REST" คือการสร้างทรัพยากรโดยใช้PUT
w / If-None-Match: *
ส่วนหัว (หรือ spec'ing วิธีการที่เหมาะสม HTTP ดูMKCOL
ฯลฯ )
ฉันไม่คิดว่าคำตอบที่ดีสำหรับโพสต์นี้จะได้รับการโพสต์ถึงแม้ว่าจะมีความคิดเห็นที่ดีมากมายเกี่ยวกับคำตอบที่มีอยู่ ฉันจะยกส่วนสำคัญของความคิดเห็นเหล่านั้นเป็นคำตอบใหม่:
ย่อหน้านี้จาก RFC7231ได้รับการยกมาสองสามครั้งซึ่งรวมกันแล้ว
เพย์โหลดภายในข้อความคำขอลบไม่มีความหมายที่กำหนดไว้ การส่งส่วนของส่วนของข้อมูลบนคำขอ DELETE อาจทำให้การใช้งานที่มีอยู่บางส่วนปฏิเสธคำขอ
สิ่งที่ฉันพลาดจากคำตอบอื่น ๆ คือความหมาย ใช่ได้รับอนุญาตให้รวมเนื้อหาตามDELETE
คำขอ แต่ไม่มีความหมายทางความหมาย นี่หมายถึงอะไรจริงๆนั่นคือการออกDELETE
คำขอด้วยเนื้อความร้องขอนั้นมีความหมายเทียบเท่ากับไม่รวมเนื้อหาของคำขอ
การรวมเนื้อหาคำขอไม่ควรมีผลกระทบใด ๆ กับคำขอดังนั้นจึงไม่มีประเด็นในการรวมคำขอ
tl; dr: DELETE
อนุญาตให้มีการร้องขอด้วยเนื้อหาของคำขอทางเทคนิค แต่ไม่มีประโยชน์ที่จะทำเช่นนั้น
ในกรณีที่มีผู้ใช้งานในการทดสอบปัญหานี้ไม่ไม่ได้รับการสนับสนุนในระดับสากล
ขณะนี้ฉันกำลังทดสอบกับ Sahi Pro และเห็นได้ชัดว่ามีการเรียก http DELETE เพื่อดึงข้อมูลใด ๆ ของร่างกาย (รายการรหัสขนาดใหญ่เพื่อลบจำนวนมากตามการออกแบบปลายทาง)
ฉันได้รับการติดต่อกับพวกเขาหลายครั้งเช่นเดียวกับที่ส่งในสามชุดที่แยกจากกันของคนร้าย, ภาพ, บันทึกเพื่อให้พวกเขาตรวจสอบและพวกเขายังไม่ได้ยืนยันเรื่องนี้ แพตช์ที่ล้มเหลวและการประชุมที่ไม่ได้รับจากฝ่ายสนับสนุนในภายหลังและฉันยังไม่ได้รับคำตอบที่ชัดเจน
ฉันแน่ใจว่า Sahi ไม่สนับสนุนสิ่งนี้และฉันคิดว่าเครื่องมืออื่น ๆ มากมายตามมาด้วยชุดเครื่องมือ
อาจเป็น URL GitHUb ด้านล่างนี้จะช่วยคุณในการรับคำตอบ ที่จริงแล้วแอปพลิเคชันเซิร์ฟเวอร์เช่น Tomcat เว็บล็อกปฏิเสธการเรียก HTTP.DELETE พร้อมคำขอเพย์โหลด ดังนั้นการรักษาทุกสิ่งไว้ในใจฉันได้เพิ่มตัวอย่างใน GitHub โปรดดูที่
ฉันสามารถใช้งานการดำเนินการ DELETE ด้วยเนื้อความคำขอ ฉันใช้เกตเวย์ AWS แลมบ์ดาและ AWS API และใช้ภาษาโก