การลบทรัพยากรโดยใช้ http DELETE


124

ดังนั้นเนื่องจากคำกริยา DELETE ใน Http เป็น idempotent เมื่อฉันออกคำขอต่อไปนี้จะเกิดอะไรขึ้นที่สอง (หรือสามหรือสี่ ฯลฯ ... )

DELETE /person/123

ครั้งแรกทรัพยากรถูกลบและฉันส่งคืน 204 (สำเร็จไม่มีเนื้อหา) ฉันควรส่งคืน 204 ในการโทรครั้งต่อ ๆ ไปหรือ 404 (ไม่พบ)?

คำตอบ:


153

เนื่องจากคำขอ HTTP ในระบบไร้รัฐควรเป็นอิสระผลลัพธ์ของคำขอหนึ่งคำขอจึงไม่ควรขึ้นอยู่กับคำขอก่อนหน้า พิจารณาว่าจะเกิดอะไรขึ้นหากผู้ใช้สองคนทำการ DELETE บนทรัพยากรเดียวกันพร้อมกัน มันสมเหตุสมผลสำหรับคำขอที่สองเพื่อรับ 404 สิ่งเดียวกันนี้ควรเป็นจริงหากผู้ใช้รายหนึ่งส่งคำขอสองครั้ง

ฉันเดาว่าการที่ DELETE ส่งคืนคำตอบที่แตกต่างกันสองคำตอบนั้นไม่ได้เป็นประโยชน์กับคุณ ฉันพบว่ามีประโยชน์ที่จะคิดว่าคำขอที่ไม่เหมาะสมเนื่องจากการออกจากระบบในสถานะเดิมไม่จำเป็นต้องได้รับการตอบสนองเดียวกัน ดังนั้นไม่ว่าคุณจะลบทรัพยากรที่มีอยู่หรือพยายามลบทรัพยากรที่ไม่มีอยู่สถานะทรัพยากรเซิร์ฟเวอร์จะเหมือนกัน


4
ขอบคุณ. นั่นทำให้รู้สึกมาก ฉันกำลังคิดว่า idempotent กลับตอบสนองเหมือนเดิม
Craig Wilson

4
@ Craig ระวัง! ในตำราอาหาร Subbu ขัดแย้งกับสิ่งที่ฉันเพิ่งพูดไป เขากล่าวว่า idempotency หมายความว่าควรกลับมาตอบสนองเหมือนเดิม โชคดีที่ Subbu กำลังจะไปที่ RESTFest ดังนั้นฉันจะชี้แจงกับเขาที่นั่น
Darrel Miller

58
หากคุณลบสิ่งที่ไม่มีอยู่คุณควรส่งคืน 204 (แม้ว่าทรัพยากรนั้นจะไม่เคยมีอยู่ก็ตาม) ลูกค้าต้องการให้ทรัพยากรหมดไปและมันก็หายไป การส่งคืน 404 เป็นการเปิดเผยการประมวลผลภายในที่ไม่สำคัญต่อไคลเอ็นต์และจะทำให้เกิดข้อผิดพลาดที่ไม่จำเป็น
Brian

9
@DarrelMiller ฉันเดาว่าแนวคิดหลักที่นี่คือคุณไม่ควรใช้ DELETE เพื่อตรวจสอบว่ามีทรัพยากรอยู่หรือไม่คุณต้องใช้ GET ก่อน จากนั้นหากคำตอบคือ 200 คุณจะต้องดำเนินการ DELETE มิฉะนั้นอย่ากังวลที่จะทำเช่นนั้น ดังนั้นฉันคิดว่ามันสมเหตุสมผลที่จะคืนค่า 204 ใน DELETE เสมอ
manei_cc

10
@Brian The RFC กล่าวว่าควรจะทำตัวเหมือนrm. rmส่งกลับข้อผิดพลาดหากไม่มีอยู่ tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl

32

ตำราการบริการเว็บ RESTful เป็นแหล่งข้อมูลที่ยอดเยี่ยมสำหรับสิ่งนี้ โดยบังเอิญตัวอย่างของ Google จะแสดงหน้าเกี่ยวกับ DELETE (หน้า 11):

เมธอด DELETE คือ idempotent นี่หมายความว่าเซิร์ฟเวอร์ต้องส่งคืนรหัสตอบกลับ 200 (OK) แม้ว่าเซิร์ฟเวอร์จะลบทรัพยากรในคำขอก่อนหน้านี้ แต่ในทางปฏิบัติการนำ DELETE ไปใช้เป็นการดำเนินการ idempotent ต้องการให้เซิร์ฟเวอร์ติดตามทรัพยากรที่ถูกลบทั้งหมด มิฉะนั้นจะสามารถส่งคืน 404 (ไม่พบ)


ใช่ดูเหมือนว่าจะเป็นแหล่งข้อมูลที่ยอดเยี่ยม อย่างไรก็ตามส่วน DELETE ไม่ได้ดึงขึ้นมาสำหรับฉัน (เป็นหน้า 23 และการแสดงตัวอย่างมีการแก้ไข) คุณอ่านหนังสือเล่มนี้แล้วหรือยัง? คุณบังเอิญรู้คำตอบสำหรับคำถามของฉันหรือไม่?
Craig Wilson

หนังสือเล่มนี้เป็นสิ่งที่ต้องมีสำหรับการสร้าง REST (พูดเป็นพิเศษไม่ใช่ภาษา)
yves amsellem

7
@ Craig อ่านตำรามันบอกว่าคุณควรคืน 200 OK แม้ว่าคุณจะลบไปแล้วก็ตาม อย่างไรก็ตามในทางปฏิบัตินั้นต้องการให้เซิร์ฟเวอร์ติดตามทรัพยากรที่ถูกลบทั้งหมดดังนั้นคุณจึงสามารถใช้ 404 ได้กล่าวต่อไปว่าข้อกังวลด้านความปลอดภัยอาจทำให้คุณต้องส่งคืน 404 เสมอหน้า 11.
Darrel Miller

+1 วินาทีและขอแนะนำหนังสือสำหรับการออกแบบบริการ RESTful
Paul DelRe

18
ดีหนังสือผิด Idempotency ไม่ได้หมายความว่ารหัสสถานะจะเหมือนกัน สิ่งที่เกี่ยวข้องคือสถานะสุดท้ายของเซิร์ฟเวอร์
Julian Reschke

13

ผมเห็นด้วยกับสิ่งที่เป็นคำตอบที่ได้รับการแต่งตั้งในปัจจุบันได้กล่าวว่าที่2 (และ 3, 4, ... ) ลบควรจะได้รับ 404 และฉันสังเกตว่าคำตอบนั้นมีคะแนนโหวต 143 คะแนน แต่ก็มีความคิดเห็นตรงข้ามซึ่งมี 54 คะแนนโหวตดังนั้นชุมชนจึงถูกแบ่งออกเป็น 2 ค่ายในอัตราส่วนประมาณ 3: 1 มาดูข้อมูลเพิ่มเติมเพื่อยุติการถกเถียงกันเป็นเวลานาน

  1. ก่อนอื่นเรามาเริ่มกันไม่ได้ว่า "ฉัน" คิดอะไร "คุณ" คิดอย่างไรหรือผู้เขียนหนังสือคนอื่นคิดอย่างไร เริ่มต้นด้วยข้อกำหนด HTTP เช่น RFC 7231

    • RFC 7231 ส่วน 4.3.5 DELETEเกิดขึ้นเพื่อกล่าวถึงเฉพาะการตอบสนองที่ประสบความสำเร็จควรเป็น 2xx แต่ไม่ได้ระบุว่าจะได้รับ DELETE ที่ตามมา มาเจาะลึกกันดีกว่า
    • RFC 7231 ส่วน 6.5.4 404 ไม่พบกล่าวว่าการตอบสนอง 404 มีไว้สำหรับทรัพยากรที่ไม่มีอยู่ เนื่องจากไม่มีการเรียกใช้เมธอด http ที่เฉพาะเจาะจง (โดยเฉพาะอย่างยิ่งไม่ใช่ DELETE) ที่ถูกเรียกให้ได้รับการปฏิบัติเป็นอย่างอื่นเราจึงได้รับการแสดงผลโดยสังหรณ์ใจ (และถูกต้องตามนั้น) ซึ่งคำขอของฉันDELETE /some/resource/which/does/not/existควรส่งผลให้เป็น 404 จากนั้นDELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/agoอาจส่งคืน 404 ด้วยเช่นกัน แล้วทำไมDELETE /some/resource/i/deleted/five/seconds/agoต้องแตกต่างกัน? "แต่ความขี้เกียจล่ะ?!" ฉันได้ยินว่าคุณกำลังกรีดร้อง เดี๋ยวก่อนเรากำลังจะเข้าสู่เรื่องนั้น
    • ในอดีต RFC 2616 เผยแพร่เมื่อปี 2542 เป็นข้อมูลจำเพาะ HTTP 1.1 ที่มีการอ้างอิงมากที่สุด น่าเสียดายคำอธิบายเกี่ยวกับ idempotency นั้นคลุมเครือซึ่งทำให้มีที่ว่างสำหรับการอภิปรายเหล่านี้ทั้งหมด แต่ข้อมูลจำเพาะนั้นถูกแทนที่โดย RFC 7231 อ้างจากRFC 7231 ส่วน 4.2.2 Idempotent Methodsเน้นของฉัน:

      วิธีการร้องขอจะถือว่าเป็น "idempotent" หากเอฟเฟกต์ที่ตั้งใจไว้บนเซิร์ฟเวอร์ของคำขอที่เหมือนกันหลายรายการด้วยวิธีการนั้นเหมือนกับผลของคำขอดังกล่าวเดียว ของวิธีการร้องขอที่กำหนดโดยข้อกำหนดนี้ PUT DELETEและวิธีการร้องขอที่ปลอดภัย เป็นสิ่งที่ไม่จำเป็น

      ดังนั้นมันถูกเขียนไว้ในรายละเอียด idempotency เป็นข้อมูลเกี่ยวกับเอฟเฟกต์บนเซิร์ฟเวอร์ DELETE แรกที่ส่งคืน 204 และหลังจากนั้น DELETE ที่ส่งคืน 404 รหัสสถานะที่แตกต่างกันดังกล่าวไม่ได้ทำให้ DELETE ไม่ใช่ idempotent การใช้อาร์กิวเมนต์นี้เพื่อแสดงให้เห็นถึงผลตอบแทน 204 ที่ตามมานั้นไม่เกี่ยวข้อง

  2. ตกลงดังนั้นมันไม่เกี่ยวกับ idempotency แต่อาจมีคำถามตามมาว่าถ้าเรายังคงเลือกใช้ 204 ใน DELETE ในภายหลัง? ตกลงหรือเปล่า

    คำถามที่ดี. แรงจูงใจเป็นสิ่งที่เข้าใจได้: เพื่อให้ลูกค้ายังคงบรรลุผลตามที่ตั้งใจไว้โดยไม่ต้องกังวลเกี่ยวกับการจัดการข้อผิดพลาด ฉันจะบอกว่าการส่งคืน 204 ใน DELETE ที่ตามมาเป็น "คำโกหกสีขาว" ฝั่งเซิร์ฟเวอร์ที่ไม่เป็นอันตรายอย่างมากซึ่งฝั่งไคลเอ็นต์จะไม่บอกความแตกต่างในทันที นั่นเป็นเหตุผลว่าทำไมถึงมีคนประมาณ 25% ที่ทำแบบนั้นในป่าและดูเหมือนว่ามันจะยังใช้ได้อยู่ เพียงจำไว้ว่าการโกหกดังกล่าวถือได้ว่าเป็นเรื่องแปลกทางความหมายเพราะGET /non-existส่งกลับ 404 แต่DELETE /non-existให้ 204 เมื่อถึงจุดนั้นลูกค้าจะคิดว่าบริการของคุณไม่เป็นไปตามมาตรา 6.5.4 404 ไม่พบอย่างสมบูรณ์

    แต่ฉันต้องการชี้ให้เห็นว่าวิธีที่ตั้งใจไว้โดย RFC 7231 คือการส่งคืน 404 ใน DELETE ที่ตามมาไม่ควรเป็นปัญหาตั้งแต่แรก นักพัฒนาอีก 3 เท่าเลือกที่จะทำเช่นนั้นและคุณเคยได้ยินเหตุการณ์สำคัญหรือเสียงบ่นที่เกิดจากลูกค้าไม่สามารถจัดการกับ 404 ได้หรือไม่? สันนิษฐานว่าไม่และนั่นเป็นเพราะไคลเอนต์ที่เหมาะสมใด ๆ ที่ใช้ HTTP DELETE (หรือวิธี HTTP ใด ๆ สำหรับเรื่องนั้น) จะไม่ถือว่าผลลัพธ์จะเป็น 2xx แบบสุ่มสี่สุ่มห้าเสมอไป จากนั้นเมื่อนักพัฒนาเริ่มพิจารณาการจัดการข้อผิดพลาด 404 Not Found จะเป็นหนึ่งในข้อผิดพลาดแรกที่เกิดขึ้นในใจ เมื่อถึงจุดนั้นเขา / เธออาจจะสรุปได้ว่าการดำเนินการ HTTP DELETE นั้นปลอดภัยในเชิงความหมายเพื่อละเว้นข้อผิดพลาด 404 และพวกเขาก็ทำเช่นนั้น

แก้ไขปัญหา.


2
+1 "idempotency เป็นข้อมูลเกี่ยวกับผลกระทบต่อเซิร์ฟเวอร์" ตอบอย่างพิถีพิถัน ทำได้ดี! ฉันเป็นผู้เชื่อ 404 สำหรับคำขอลบในภายหลัง
nwayve

11

ลบครั้งแรก : 200 หรือ 204

การลบในภายหลัง : 200 หรือ 204

เหตุผล : DELETE ควรเป็น idempotent หากคุณส่งคืน 404 ใน DELETE วินาทีการตอบกลับของคุณกำลังเปลี่ยนจากรหัสสำเร็จเป็นรหัสข้อผิดพลาดรหัสข้อผิดพลาดโปรแกรมไคลเอ็นต์อาจดำเนินการที่ไม่ถูกต้องตามข้อสันนิษฐานว่า DELETE ล้มเหลว

ตัวอย่าง :

  • สมมติว่าการดำเนินการ DELETE ของคุณเป็นส่วนหนึ่งของการดำเนินการหลายขั้นตอน (หรือ "saga") ที่ดำเนินการโดยโปรแกรมไคลเอ็นต์
  • โปรแกรมลูกค้าอาจเป็นแอปบนอุปกรณ์เคลื่อนที่ที่ทำธุรกรรมทางธนาคารเป็นต้น
  • สมมติว่าโปรแกรมไคลเอนต์มีการลองใหม่โดยอัตโนมัติสำหรับการดำเนินการ DELETE (มันสมเหตุสมผลเพราะ DELETE ควรจะเป็น idempotent)
  • สมมติว่าการดำเนินการ DELETE ครั้งแรกประสบความสำเร็จ แต่การตอบกลับ 200 ครั้งหายไประหว่างทางไปยังโปรแกรมไคลเอ็นต์
  • โปรแกรมไคลเอนต์จะลอง DELETE อีกครั้ง
  • หากความพยายามครั้งที่สองส่งคืน 404 โปรแกรมไคลเอนต์อาจยกเลิกการดำเนินการโดยรวมเนื่องจากรหัสข้อผิดพลาดนี้
  • แต่เนื่องจากครั้งแรก DELETE ดำเนินการประสบความสำเร็จบนเซิร์ฟเวอร์ระบบอาจจะทิ้งไว้ที่สถานะไม่สอดคล้องกัน
  • หากความพยายามครั้งที่สองส่งกลับ 200 หรือ 204 โปรแกรมไคลเอนต์จะดำเนินการตามที่คาดไว้

เพื่อแสดงให้เห็นถึงการใช้แนวทางนี้คำแนะนำสไตล์ HTTP API สำหรับ PayPalมีแนวทางดังต่อไปนี้:

ลบ: วิธีนี้ควรส่งคืนรหัสสถานะ 204 เนื่องจากไม่จำเป็นต้องส่งคืนเนื้อหาใด ๆ ในกรณีส่วนใหญ่เนื่องจากคำขอคือการลบทรัพยากรและลบได้สำเร็จ

เนื่องจากเมธอด DELETE ต้องเป็น idempotent เช่นกันจึงควรส่งคืน 204 แม้ว่าทรัพยากรจะถูกลบไปแล้วก็ตาม โดยปกติผู้บริโภค API ไม่สนใจว่าทรัพยากรถูกลบเนื่องจากเป็นส่วนหนึ่งของการดำเนินการนี้หรือก่อนหน้านี้ นี่เป็นเหตุผลว่าทำไมควรส่งคืน 204 แทน 404


1
คำถามคือสิ่งที่สำคัญไปยังลูกค้าที่มันลบทรัพยากรหรือทรัพยากรได้ถูกลบออก จะเกิดอะไรขึ้นถ้าไคลเอนต์อื่นลบทรัพยากรในระหว่างการผจญภัย คุณต้องการล้มเหลวในการพิจารณาว่าบรรลุวัตถุประสงค์ของลูกค้าหรือไม่?
Darrel Miller

1
@DarrelMiller จุดดี. สิ่งที่สำคัญกว่าขึ้นอยู่กับบริบททางธุรกิจ แต่โดยทั่วไปแล้วฉันควรส่งคืน 204 ในการพยายามลบครั้งที่สองแม้ว่าไคลเอ็นต์อื่นจะลบทรัพยากรก็ตาม ฉันไม่ต้องการให้บริการล้มเหลว (เช่น 404) เนื่องจากบรรลุวัตถุประสงค์ของลูกค้า
Paulo Merson

2
ดังที่คนอื่น ๆ กล่าวไว้ idempotency ไม่ใช่รหัสตอบกลับของคุณ แต่เป็นสถานะเซิร์ฟเวอร์ของคุณ
Niranjan

@ Niranjan ฉันยอมรับว่า idempotency เป็นเรื่องเกี่ยวกับสถานะเซิร์ฟเวอร์ แต่รหัสตอบกลับที่แตกต่างกันอาจผลักดันให้ไคลเอนต์เปลี่ยนสถานะเซิร์ฟเวอร์โดยไม่จำเป็นโดยการยกเลิกเทพนิยายที่กำลังดำเนินอยู่
Paulo Merson

@Paulo Merson คุณจะคืนรหัสอะไรหากลูกค้าขอให้ลบรายการที่ไม่เคยมีอยู่? 204? หรือ 404? หากคุณส่งคืน 204 เสมอจุดในการตรวจสอบรหัสคืนสินค้าคืออะไร?
frenchone
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.