REST DELETE idempotent จริงๆหรือ


166

DELETE ควรจะเป็น idempotent

หากฉันลบhttp://example.com/account/123จะเป็นการลบบัญชี

ถ้าฉันทำอีกฉันจะคาดหวัง 404 เนื่องจากบัญชีไม่มีอยู่อีกต่อไป? ถ้าฉันพยายามลบบัญชีที่ไม่เคยมีอยู่จะทำอย่างไร


11
นอกเหนือจากคำตอบแล้วฉันไม่แนะนำให้สนใจลักษณะทั่วไปของ idempotent มากเกินไป: มันไม่ได้พูดอะไรเกี่ยวกับการสับเปลี่ยนและการร้องขอพร้อมกัน ตัวอย่างเช่น N + 1 ของคำขอ "R1" PUT เดียวกันควรมีผลเหมือนกัน แต่คุณไม่รู้ว่าลูกค้าอื่นทำคำขอ PUT / DELETE "R2" ที่แตกต่างกันในระหว่างของคุณหรือไม่ดังนั้นในขณะที่ n R1 = R1 และ m R2 = R2 สิ่งที่คุณได้รับคำขอ "R1" และ "R2" interleaved ไม่จำเป็นต้อง "มอง" idempotent ถ้าคุณใช้มุมมองของลูกค้าเพียงคนเดียว
บรูโน

คำตอบ:


189

Idempotence อ้างถึงสถานะของระบบหลังจากการร้องขอเสร็จสมบูรณ์


ในทุกกรณี (นอกเหนือจากปัญหาข้อผิดพลาด - ดูด้านล่าง) บัญชีไม่มีอยู่อีกต่อไป

จากที่นี่

"เมธอดยังสามารถมีคุณสมบัติของ" idempotence "ในนั้น ( นอกเหนือจากข้อผิดพลาดหรือปัญหาการหมดอายุ ) ผลข้างเคียงของ N> 0 คำร้องขอเหมือนกันเหมือนกับการร้องขอครั้งเดียววิธีแบ่งปัน GET, HEAD, PUT และ DELETE คุณสมบัตินี้นอกจากนี้วิธีการตัวเลือกและการติดตามไม่ควรมีผลข้างเคียงและดังนั้นจึงเป็น idempotent โดยเนื้อแท้ "


บิตที่สำคัญมีผลข้างเคียงของคำขอที่เหมือนกันของ N> 0 จะเหมือนกับในคำขอเดี่ยว

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


3
ผลข้างเคียง! == สถานะเซิร์ฟเวอร์
wprl

2
@wprl มีการถกเถียงกันว่า "ผลข้างเคียง" นี้คืออะไร อาจเป็น "สถานะเซิร์ฟเวอร์" หรืออาจเป็นคำตอบที่ส่งถึงลูกค้า leedavis81.github.io/is-a-http-delete-requests-idempotent
Alireza

นี่คือข้อโต้แย้งว่า 404 ในการลบครั้งที่สองอาจเปลี่ยนสถานะของเซิร์ฟเวอร์จริง ๆ : stackoverflow.com/a/45194747/317522
Paulo Merson

1
@ พอลโลเมอร์สันขอบคุณโดยส่วนตัวฉันไม่คิดว่ามันสำคัญว่าการคืนที่สองคือ 404 หรือ 200 สถานะของเซิร์ฟเวอร์ไม่เปลี่ยนแปลงดังนั้นฉันจึงมีความสุขกับมัน
Chris McCauley

46

Idempotentเป็นเรื่องเกี่ยวกับผลกระทบของการร้องขอไม่ใช่เกี่ยวกับรหัสการตอบสนองที่คุณได้รับ

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2พูดว่า:

เมธอดยังสามารถมีคุณสมบัติของ "idempotence" ในนั้น (นอกเหนือจากข้อผิดพลาดหรือปัญหาการหมดอายุ) ผลข้างเคียงของ N> 0 คำขอที่เหมือนกันจะเหมือนกันสำหรับคำขอเดียว

ในขณะที่คุณอาจได้รับรหัสการตอบสนองที่แตกต่างกันผลของการส่งคำขอ N + 1 DELETE ไปยังทรัพยากรเดียวกันก็ถือได้ว่าเหมือนกัน


13

ความแตกต่างที่สำคัญคือ idempotent หมายถึงผลข้างเคียงที่ไม่ทั้งหมด -effects หรือการตอบสนอง หากคุณทำเช่นDELETE http://example.com/account/123นั้นเอฟเฟกต์คือบัญชี 123 จะถูกลบออกจากเซิร์ฟเวอร์ นั่นคือเอฟเฟกต์หนึ่งเดียวเท่านั้นการเปลี่ยนแปลงเพียงครั้งเดียวจะเปลี่ยนเป็นสถานะของเซิร์ฟเวอร์ ตอนนี้สมมติว่าคุณทำDELETE http://example.com/account/123คำขอเดียวกันอีกครั้งเซิร์ฟเวอร์จะตอบกลับต่างกัน แต่สถานะของมันจะเหมือนกัน

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


7

จากHTTP RFC :

เมธอดยังสามารถมีคุณสมบัติของ "idempotence" ในนั้น (นอกเหนือจากข้อผิดพลาดหรือปัญหาการหมดอายุ) ผลข้างเคียงของ N> 0 คำขอที่เหมือนกันจะเหมือนกันสำหรับคำขอเดียว

โปรดทราบว่า "ผลข้างเคียง" ไม่ใช่ "การตอบสนอง"


7

ใช่. โดยไม่คำนึงถึงรหัสการตอบสนอง

จากRFC ล่าสุดสำหรับ HTTP 1.1 (เหมืองที่เน้น):

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

มันบอกอย่างชัดเจนว่าการตอบสนองอาจแตกต่างกัน ที่สำคัญกว่านั้นคือมันแสดงให้เห็นถึงเหตุผลของแนวคิด: หากการกระทำนั้นเป็น idempotent ลูกค้าสามารถทำซ้ำการกระทำได้เมื่อพบข้อผิดพลาดและรู้ว่าจะไม่เกิดปัญหาใด ๆ จากการทำเช่นนั้น ถ้าไม่ลูกค้าจะต้องทำแบบสอบถามเพิ่มเติม (อาจGET) เพื่อดูว่าก่อนหน้านี้มีประสิทธิภาพก่อนที่จะทำซ้ำการกระทำที่ปลอดภัย ตราบใดที่เซิร์ฟเวอร์สามารถรับประกันได้การกระทำก็คือ idempotent อ้างอิงจากความคิดเห็นอื่น :

การคำนวณ idempotenceนั้นเกี่ยวกับความทนทานของระบบ เนื่องจากสิ่งต่าง ๆ สามารถล้มเหลว (เช่นเครือข่ายดับ), เมื่อตรวจพบความล้มเหลวคุณจะกู้คืนได้อย่างไร? การกู้คืนที่ง่ายที่สุดคือการทำมันอีกครั้ง แต่วิธีนี้ใช้ได้ผลถ้าทำอีกครั้งคือ idempotent เช่นdiscard(x)idempotent แต่pop()ไม่ใช่ มันคือทั้งหมดที่เกี่ยวกับการกู้คืนข้อผิดพลาด


3

อ้างจากคำตอบอื่นของฉันที่นี่ :

ในอดีต RFC 2616 ซึ่งตีพิมพ์เมื่อปี 1999 เป็นรายละเอียด HTTP 1.1 ที่มีการอ้างอิงมากที่สุด น่าเสียดายที่คำอธิบายเกี่ยวกับ idempotency นั้นคลุมเครือซึ่งทำให้พื้นที่สำหรับการอภิปรายทั้งหมดนี้ แต่รายละเอียดดังกล่าวถูกแทนที่โดย RFC 7231 ยกมาจากRFC 7231 ส่วน 4.2.2 วิธี Idempotentเน้นการทำเหมือง:

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

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


ตกลงดังนั้นมันไม่เกี่ยวกับ idempotency แต่คำถามติดตามอาจเกิดอะไรขึ้นถ้าเรายังคงเลือกใช้ 204 ในการลบครั้งต่อไป ตกลงหรือไม่

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

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


2

ฉันคิดเหมือนกัน 404 - บัญชีไม่มีอยู่

คุณสามารถโต้แย้ง 400 - คำขอไม่ถูกต้อง แต่ในแง่ของ REST วัตถุที่คุณขอให้ดำเนินการจะไม่ปรากฏขึ้น นั่นแปลเป็น 404


1
เพื่อสร้าง 400 คุณจะต้องรู้ว่าวัตถุที่เคยมีอยู่ซึ่งไม่สงบมาก
annakata

1
@annakata, 400 ไม่ได้มีไว้สำหรับทรัพยากรที่เคยมีอยู่ (บางทีคุณมี 410 / Gone ในใจ) มันมีไว้สำหรับคำขอที่ไม่ดี"เซิร์ฟเวอร์ไม่สามารถเข้าใจคำขอเนื่องจากไวยากรณ์ผิดรูปแบบ"
บรูโน

3
@Bruno - ฉันรู้ว่ามันหมายถึงอะไร OP อ้างถึงมัน
annakata

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