REST, HTTP DELETE และพารามิเตอร์


135

มีอะไรที่ไม่เกี่ยวข้องกับการระบุพารามิเตอร์ให้กับคำขอ HTTP DELETE หรือไม่


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

วิธีแก้ปัญหาที่เรานำมาใช้คือการส่งพารามิเตอร์ไปยังคำขอลบเพื่อระบุว่าสามารถดำเนินการลบได้ ("? force_delete = true")

เช่น

DELETE http://server/resource/id?force_delete=true

ฉันเชื่อว่ามันยังคงผ่อนคลายตั้งแต่:

(a) ไม่มีการเปลี่ยนแปลงความหมายของ DELETE - ผู้ใช้ยังคงสามารถส่งคำขอ DELETE ตามปกติได้ แต่อาจล้มเหลวด้วย 409 และเนื้อหาของการตอบกลับจะอธิบายสาเหตุ ฉันบอกว่าอาจล้มเหลวเนื่องจาก (ด้วยเหตุผลที่ไม่คุ้มค่าที่จะอธิบาย) ในบางครั้งไม่มีเหตุผลที่จะแจ้งให้ผู้ใช้ทราบ

(b) ไม่มีอะไรในวิทยานิพนธ์ของ Roy ที่ชี้ให้เห็นว่ามันขัดต่อเจตนารมณ์ของ REST - ทำไมถึงเป็นเช่นนั้นเนื่องจาก HTTP เป็นเพียงการใช้งาน REST เพียงครั้งเดียวดังนั้นทำไมการส่งผ่านพารามิเตอร์ HTTP จึงมีความสำคัญ


ใครช่วยชี้ฉันด้วยคำพูดที่ชัดเจนว่าทำไมสิ่งนี้ถึงไม่สงบ?

ในคำถามที่เกี่ยวข้องหากผู้ใช้ไม่ได้ระบุ force_delete ฉันจะส่งคืน409 Conflict- รหัสตอบกลับที่เหมาะสมที่สุดหรือไม่


ติดตาม

หลังจากการวิจัยเพิ่มเติมฉันคิดว่าการเพิ่มพารามิเตอร์ใน DELETE อาจละเมิดหลักการหลายประการ

ประการแรกคือการใช้งานอาจละเมิด "Uniform Interface" (ดูหัวข้อ 5.1.5 ของวิทยานิพนธ์ของ Roy

ด้วยการเพิ่ม 'force_delete' เรากำลังเพิ่มข้อ จำกัด เพิ่มเติมในเมธอด DELETE ที่กำหนดไว้อย่างดี ข้อ จำกัด นี้มีความหมายสำหรับเราเท่านั้น

นอกจากนี้คุณยังสามารถโต้แย้งได้ว่าละเมิด "5.1.2 ไคลเอนต์ - เซิร์ฟเวอร์" เนื่องจากกล่องโต้ตอบการยืนยันเป็นปัญหาเกี่ยวกับ UI และลูกค้าบางรายอาจไม่ต้องการยืนยันการลบ

มีใครแนะนำไหม


1
URL ของคุณสำหรับวิทยานิพนธ์รอยมี ")" ที่ทำให้ 404 ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htmงาน
NuclearPeon

คำตอบ:


78

ไม่มันไม่สงบ เหตุผลเดียวที่คุณควรใส่คำกริยา ( force_delete) ลงใน URI คือถ้าคุณต้องการโอเวอร์โหลดเมธอด GET / POST ในสภาพแวดล้อมที่ไม่มีเมธอด PUT / DELETE เมื่อพิจารณาจากการใช้เมธอด DELETE ของคุณไม่เป็นเช่นนั้น

409/Conflictควรใช้รหัสข้อผิดพลาด HTTP สำหรับสถานการณ์ที่มีข้อขัดแย้งซึ่งขัดขวางไม่ให้บริการ RESTful ดำเนินการ แต่ยังมีโอกาสที่ผู้ใช้อาจสามารถแก้ไขข้อขัดแย้งได้ด้วยตนเอง การยืนยันก่อนการลบ (ในกรณีที่ไม่มีความขัดแย้งที่แท้จริงซึ่งจะป้องกันการลบ) ไม่ใช่ข้อขัดแย้งใด ๆ เนื่องจากไม่มีสิ่งใดป้องกันไม่ให้ API ดำเนินการตามที่ร้องขอ

อย่างที่อเล็กซ์พูด (ฉันไม่รู้ว่าใครลงคะแนนเขาถูกต้อง) สิ่งนี้ควรได้รับการจัดการใน UI เนื่องจากบริการ RESTful ดังกล่าวเป็นเพียงการดำเนินการตามคำขอและควรเป็นแบบไร้สัญชาติ (กล่าวคือต้องไม่อาศัยการยืนยันโดยการถือ ข้อมูลฝั่งเซิร์ฟเวอร์ใด ๆ เกี่ยวกับคำขอ)

สองตัวอย่างวิธีการทำใน UI คือ:

  • pre-HTML5 : * แสดงกล่องโต้ตอบการยืนยัน JS ให้กับผู้ใช้และส่งคำขอก็ต่อเมื่อผู้ใช้ยืนยัน
  • HTML5 : * ใช้แบบฟอร์มที่มีการดำเนินการ DELETE โดยที่แบบฟอร์มจะมีเพียงปุ่ม "ยืนยัน" และ "ยกเลิก" ("ยืนยัน" จะเป็นปุ่มส่ง)

(*) โปรดทราบว่า HTML เวอร์ชันก่อนหน้า 5 ไม่รองรับเมธอด PUT และ DELETE โดยกำเนิด แต่เบราว์เซอร์สมัยใหม่ส่วนใหญ่สามารถใช้สองวิธีนี้ผ่านการเรียก AJAX ดูหัวข้อนี้สำหรับรายละเอียดเกี่ยวกับการรองรับข้ามเบราว์เซอร์


อัปเดต (ขึ้นอยู่กับการตรวจสอบและการอภิปรายเพิ่มเติม):

สถานการณ์ที่บริการต้องการให้มีการforce_delete=trueตั้งค่าสถานะละเมิดอินเตอร์เฟสที่เหมือนกันตามที่กำหนดไว้ในวิทยานิพนธ์ของ Roy Fielding นอกจากนี้ตามHTTP RFCเมธอด DELETE อาจถูกแทนที่บนเซิร์ฟเวอร์ต้นทาง (ไคลเอนต์) ซึ่งหมายความว่าสิ่งนี้ไม่ได้ทำบนเซิร์ฟเวอร์เป้าหมาย (บริการ)

ดังนั้นเมื่อบริการได้รับคำขอ DELETE ควรดำเนินการโดยไม่จำเป็นต้องมีการยืนยันเพิ่มเติม (ไม่ว่าบริการจะดำเนินการจริงหรือไม่ก็ตาม)


2
คุณช่วยอธิบายได้ไหมว่าข้อ จำกัด REST ใดที่ถูกละเมิด เมื่อพิจารณาว่า URI ควรเป็นแบบทึบสำหรับไคลเอ็นต์เหตุใดคุณจึงเชื่อว่าความคาดหวังของลูกค้าไม่ตรงตามการใช้ HTTP DELETE ที่ลบทรัพยากรหนึ่ง แต่ไม่สามารถลบอีกรายการหนึ่งได้ ฉันไม่แน่ใจว่า 409 เป็นรหัสสถานะที่ดีที่สุดในการส่งคืน แต่นอกเหนือจากการใช้งานที่แปลก ๆ แล้วฉันไม่พบข้อ จำกัด REST ใด ๆ ที่กำลังเสีย
Darrel Miller

2
@Darrel: (imho) มันละเมิดอินเทอร์เฟซที่เหมือนกันโดยวิธี DELETE ไม่ทำงานตามมาตรฐาน HTTP พิจารณาไคลเอนต์ REST ซึ่งถือว่าเป็นบริการ REST มาตรฐาน - บริการจะแจ้งให้ลูกค้าทราบได้อย่างไรว่าจำเป็นต้องเพิ่มforce_delete=true? ตาม HTTP RFC เมธอด DELETE อาจถูกลบล้างบนเซิร์ฟเวอร์ต้นทาง (ไคลเอนต์) ซึ่งหมายความว่าสิ่งนี้ไม่ได้ทำบนเซิร์ฟเวอร์เป้าหมาย (บริการ) ดังนั้นความเข้าใจของฉันก็คือเมื่อบริการได้รับคำขอ DELETE แล้วควรดำเนินการโดยไม่ต้องการการยืนยันใด ๆ (ไม่ว่าบริการจะดำเนินการจริงหรือไม่ก็ตาม)
MicE

1
@ คริสถึงจุดที่สองของคุณ: ใช่นั่นคือความเข้าใจของฉันเช่นกันกล่าวคือรัฐเสนอความขัดแย้งที่แท้จริงและไม่จำเป็นต้องมีการยืนยัน ฉันเพิ่งสังเกตเห็นการอัปเดตที่คุณทำในคำถามของคุณและฉันยอมรับ - ในขณะที่ฉันกำลังตรวจสอบด้วยตัวเองฉันก็ได้ข้อสรุปแบบเดียวกัน (ว่าสิ่งนี้ละเมิดอินเทอร์เฟซที่เหมือนกันและควรทำการยืนยันบนไคลเอนต์ / UI ข้าง) ฉันยังพบหัวข้อที่น่าสนใจมากที่นี่ซึ่งอาจช่วยได้: mail-archive.com/pylons-discuss@googlegroups.com/msg13578.html
MicE

2
@MicE ในระดับใหญ่ฉันเห็นด้วยกับคุณว่ามันไม่ใช่วิธีที่ดีที่สุดในการจัดการกับสถานการณ์นี้ ฉันแค่จู้จี้จุกจิกเล็กน้อยเกี่ยวกับป้ายกำกับ "It's not RESTful" ชั่วขณะที่วลีนั้นถูกโยนทิ้งไปทุกอย่าง อย่างไรก็ตามเป็นไปได้ที่จะกำหนดกฎสำหรับประเภทสื่อที่ระบุว่าหากคุณพยายามลบทรัพยากรและคุณได้รับข้อผิดพลาด (ฉันจะบอกว่าห้ามใช้ 403 จะดีกว่า 409) จากนั้นไคลเอนต์ควรพยายามลบทรัพยากรที่เกี่ยวข้อง โดยใช้ "force_delete = true" มันเหมือนกับการอนุญาตเล็กน้อย ทำ GET รับ 401 เพิ่มส่วนหัวรับรองความถูกต้องและรับอีกครั้ง
Darrel Miller

2
@ Darrel: นั่นเป็นจุดที่ดีมากขอบคุณ และฉันเคยเห็นผู้คนโยนฉลากnot RESTful ให้ตัวเอง อาจเป็นกรณีที่ปัจจุบันกำแพงกั้นระหว่างบริการและเว็บแอปพลิเคชันมีหมอกหนามากดังนั้นผู้คนกลุ่มหนึ่งสามารถมองเห็นสิ่งนี้จากมุมมองของบริการที่แท้จริงในขณะที่คนอื่น ๆ มองเห็นจากมุมมองของแอปพลิเคชัน / บริการแบบผสม นั่นคือฉันเชื่อว่าคำถามจริงเกี่ยวกับวิธีการยืนยันเข้ามามีบทบาท @Chris: อัปเดต - ขอบคุณสำหรับหัวข้อและการสนทนาที่น่าสนใจมาก!
MicE

35

ฉันคิดว่านี่ไม่ใช่การพักผ่อน ฉันไม่คิดว่าบริการพักผ่อนควรจัดการกับข้อกำหนดในการบังคับให้ผู้ใช้ยืนยันการลบ ฉันจะจัดการสิ่งนี้ใน UI

การระบุ force_delete = true เหมาะสมหรือไม่หากเป็น API ของโปรแกรม หากมีคนเขียนสคริปต์เพื่อลบทรัพยากรนี้คุณต้องการบังคับให้ระบุ force_delete = true เพื่อลบทรัพยากรจริงหรือไม่


ย่อหน้าแรกของคำตอบของคุณคือความคิดเห็นของคุณและฉันเคารพในสิ่งนั้น แต่คุณไม่ได้ชี้ถึงบางสิ่งในวรรณกรรมที่ห้ามใช้ URI เช่นนี้ - มันยังคงระบุทรัพยากรและมีการใช้คำกริยา HTTP ที่เหมาะสมที่สุด เพื่อตอบคำถามของคุณ ใช่มันก็ยังสมเหตุสมผล (ในความคิดของฉัน) ฉันคาดหวังว่าสคริปต์ (อาจอิงตาม CURL) เพื่อเคารพการตอบสนอง 409 และแนะนำให้ผู้ใช้ทราบว่าคำขอจะไม่พอใจได้อย่างไร - ทั้งหมดนี้ขึ้นอยู่กับเนื้อหาการตอบสนองของฉัน
Chris McCauley

ข้อดีของการเปรียบเทียบ Web API กับ API ของโปรแกรม นี่เป็นวิธีที่ดีในการตรวจสอบว่า API เป็น RESTful หรือไม่
laurent

18

เป็นคำถามเก่า แต่นี่คือความคิดเห็นบางส่วน ...

  1. ใน SQL คำสั่ง DELETE ยอมรับพารามิเตอร์ "CASCADE" ซึ่งอนุญาตให้คุณระบุว่าควรลบอ็อบเจ็กต์ที่เกี่ยวข้องด้วย นี่คือตัวอย่างของพารามิเตอร์ DELETE ที่สมเหตุสมผล แต่ 'man rm' สามารถให้ข้อมูลอื่น ๆ ได้ กรณีเหล่านี้จะนำไปใช้ใน REST / HTTP โดยไม่มีพารามิเตอร์ได้อย่างไร
  2. @Jan ดูเหมือนว่าจะเป็นแบบแผนที่กำหนดไว้อย่างดีว่าส่วนของเส้นทางของ URL ระบุทรัพยากรในขณะที่สตริงการสืบค้นไม่ได้ (อย่างน้อยก็ไม่จำเป็น) ตัวอย่างมากมาย: การได้รับทรัพยากรเดียวกัน แต่อยู่ในรูปแบบที่แตกต่างกันการได้รับฟิลด์เฉพาะของทรัพยากร ฯลฯ หากเราพิจารณาสตริงการสืบค้นเป็นส่วนหนึ่งของตัวระบุทรัพยากรเป็นไปไม่ได้ที่จะมีแนวคิด "มุมมองที่แตกต่างกันของทรัพยากรเดียวกัน" โดยไม่หันไปใช้กลไกที่ไม่เป็นที่ต้องการเช่นการเจรจาต่อรองเนื้อหา HTTP (ซึ่งอาจไม่เป็นที่ต้องการด้วยเหตุผลหลายประการ)

ขอขอบคุณที่เพิ่มสิ่งนี้ในการสนทนาแม้ว่าการสนทนาจะไม่มากนักเนื่องจากใช้เวลาหลายปี
silviot

6

นอกจากคำตอบของ Alex:

โปรดทราบว่าhttp: // server / ทรัพยากร / ID force_delete = trueระบุทรัพยากรที่แตกต่างจากhttp: // เซิร์ฟเวอร์ / ทรัพยากร / ID ตัวอย่างเช่นความแตกต่างอย่างมากไม่ว่าคุณจะลบ / ลูกค้า /? status = เก่าหรือ / ลูกค้า /

ม.ค.


ฉันไม่เห็นด้วยฉันมีอิสระที่จะระบุ URI หลายรายการเพื่อระบุทรัพยากรเดียวกัน
Chris McCauley

19
ใช่ - ทุกคนมีอิสระที่จะยุ่ง :-)
Jan Algermissen

การระบุ URI แบบบัญญัติสามารถช่วยได้: googlewebmastercentral.blogspot.com/2009/02/…
MicE

@Chris ควรมีเพียง URI เดียวที่ส่งคืนการเป็นตัวแทนของทรัพยากร URI อื่น ๆ สามารถอ้างถึงแนวคิดเดียวกัน แต่การทำ GET ควรส่งคืน 303 See Other และเพื่อตอบโต้การคัดค้านที่ชัดเจนต่อสิ่งนี้ /foo.xml และ /foo.json เป็นแหล่งข้อมูลที่แตกต่างกันสองแหล่ง
Darrel Miller

@Darrell - เห็นด้วย แต่รูปแบบไม่ใช่ปัญหาที่นี่ นอกจากนี้. format ยังเป็นแบบแผนใน Rails และเฟรมเวิร์กอื่น ๆ ที่ไม่ได้เป็นส่วนหนึ่งของ REST คุณควรใช้การต่อรองเนื้อหาใน HTTP กับ MIME หรือไมโครฟอร์แมตเพื่อนำไปใช้อย่างเต็มที่
Chris McCauley
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.