ใช้ PUT โดยมีผลกระทบด้านข้างที่ยอมรับได้ (REST)


9

ฉันต้องการสร้างประวัติการเลิกทำเมื่อใดก็ตามที่ผู้ใช้อัปเดตฟอร์ม เนื่องจากเป็นการอัปเดตฉันต้องการใช้คำขอ PUT แต่ผมอ่านที่ความต้องการนำไปไม่มีผลข้างเคียง

เป็นที่ยอมรับหรือไม่ที่จะใช้ PUT ที่นี่ มีทางเลือกที่ดีกว่านี้ไหม?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

ในเซิร์ฟเวอร์

doPut('person/:personId',
   // create a new person snapshot
)

แก้ไข:

ผู้ใช้จะสามารถเห็นประวัติได้การเรียกหลายครั้งจะทำให้หลายเวอร์ชัน

วิธีแก้ไขคือการตรวจสอบว่าเป็นรุ่นที่ไม่ซ้ำกันก่อนที่จะสร้างมัน

คำตอบ:


11

ผู้คนที่ร่าง HTTP / 2 นั้นมีความเห็นที่ชัดเจนเกี่ยวกับความคิดของพวกเขาว่า HTTP ควรทำอะไรในขณะที่ยังคงรักษาความหมายเดิมไว้ มาดูสิ่งที่ร่าง HTTP / 2 มีการพูดเกี่ยวกับ idempotence:

4.2.2 วิธีการ Idempotent

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

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

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

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


การแก้ไขของคุณ:

ผู้ใช้จะมองเห็นประวัติได้การโทรหลายครั้งจะส่งผลให้เกิดการสลับหลายครั้ง

เท่าที่ทรัพยากรที่เป็นห่วงว่าจะไม่มีผลข้างเคียง ทรัพยากรที่ URI นั้นไม่เปลี่ยนแปลง (คุณสมบัติเดียวกันรับ PUT) ประวัติเป็นเพียงข้อมูลเมตาเนื่องจากมีการร้องขอมากที่สุดโดย URI อื่นหรือมีส่วนหัวคำขอที่แตกต่างกัน


ยกเว้นเพราะคุณตอบปัญหาเฉพาะของฉัน: "เป็นที่ยอมรับสำหรับ PUT ในการสร้างประวัติผู้ใช้ที่มองเห็นได้" และให้ทางออกฉันขอบคุณ
roo2

ปัญหาอะไรคือทางออก? ว่าtimeคุณสมบัติที่ได้รับการปรับปรุง? ฉันคิดว่าเป็นข้อมูลเมตาเช่นกันแม้ว่าจะอยู่ในทรัพยากร
CodeCaster

1
ปัญหาคือว่าถ้ามีการส่ง PUT หลายครั้งผู้ใช้จะได้รับประวัติเลิกทำที่ยาวนานพร้อมด้วยข้อมูลซ้ำซ้อน การตรวจสอบความเป็นเอกลักษณ์ช่วยแก้ปัญหานั้น
roo2

12

HTTP แยกความแตกต่างระหว่างสองคุณสมบัติ:

  • Idempotency
  • ความปลอดภัย

Idempotency ถูกกำหนดโดย spec ดังต่อไปนี้:

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

และความปลอดภัย:

โดยเฉพาะอย่างยิ่งการประชุมได้รับการจัดตั้งขึ้นที่GETและHEADวิธีการไม่ควรมีความสำคัญของการดำเนินการอื่นนอกเหนือจากการดึง วิธีการเหล่านี้ควรได้รับการพิจารณาว่า " ปลอดภัย " นี้จะช่วยให้ตัวแทนผู้ใช้เพื่อเป็นตัวแทนของวิธีการอื่น ๆ เช่นPOST, PUTและDELETEในวิธีพิเศษเพื่อให้ผู้ใช้จะได้รับรู้ถึงความจริงที่ว่าการกระทำที่อาจจะไม่ปลอดภัยมีการร้องขอ

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

โปรดทราบว่าความปลอดภัยหมายถึง idempotency: หากวิธีการไม่มีผลข้างเคียงจากนั้นการดำเนินการหลายครั้งจะให้ผลข้างเคียงเช่นเดียวกับการทำเพียงครั้งเดียวคือไม่มี

สิ่งนี้ทำให้วิธีการเป็นสามประเภท:

  • ปลอดภัย (และยัง idempotent): GET, HEAD, OPTION,TRACE
  • idempotent แต่ไม่จำเป็นต้องปลอดภัย: PUT,DELETE
  • idempotent และไม่ปลอดภัย: POST

วางต้องไม่มีผลข้างเคียง

ว่าเป็นสิ่งที่ผิด. PUTidempotent แต่ไม่ปลอดภัย จุดรวมของการPUTที่จะมีผลข้างเคียงคือการปรับปรุงทรัพยากร idempotency หมายความว่าการอัพเดตทรัพยากรเดียวกันด้วยเนื้อหาเดียวกันหลาย ๆ ครั้งควรมีผลเช่นเดียวกับการอัพเดตเพียงครั้งเดียว

จดบันทึกย่อหน้าสุดท้ายในส่วนเกี่ยวกับความปลอดภัย [เหมืองของการเน้น]

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

แม้ว่าประโยคนี้จะพูดถึงGETและปลอดภัย แต่เราสามารถสันนิษฐานได้ว่าผู้เขียนตั้งใจใช้เหตุผลเดียวกันกับPUTidempotency IOW: PUTควรมีผลข้างเคียงที่ผู้ใช้เห็นได้เพียงครั้งเดียวนั่นคือการอัพเดตทรัพยากรที่มีชื่อ มันอาจมีผลข้างเคียงอื่น ๆ แต่ผู้ใช้ไม่สามารถรับผิดชอบต่อพวกเขา

ตัวอย่างเช่นความจริงที่ว่าPUTidempotent หมายความว่าฉันสามารถลองใหม่ได้บ่อยเท่าที่ต้องการ: สเป็ครับประกันว่าการดำเนินการหลายครั้งจะเหมือนกับการดำเนินการเพียงครั้งเดียว สามารถใช้งานได้อย่างสมบูรณ์แบบในการสร้าง backlog ของการแก้ไขแบบเก่าซึ่งเป็นผลข้างเคียงของPUTคำขอหลาย ๆ อย่างไรก็ตามหากเป็นผลมาจากการลองซ้ำหลายครั้งฐานข้อมูลของคุณจะเต็มไปด้วย backlog ของการแก้ไขเก่านั่นไม่ใช่ปัญหาของฉันมันเป็นของคุณ

IOW: คุณได้รับอนุญาตให้มีผลข้างเคียงได้มากเท่าที่คุณต้องการ แต่

  1. มันต้องมองไปที่ผู้ใช้ราวกับว่าคำขอของพวกเขานั้นเป็น idempotent
  2. คุณต้องรับผิดชอบต่อผลข้างเคียงเหล่านั้นไม่ใช่ผู้ใช้

ใช่ idempotency เกี่ยวกับสถานะของทรัพยากรที่ถูกวางไม่ใช่เกี่ยวกับสถานะเซิร์ฟเวอร์ / บริการอื่นใดที่ได้รับผลกระทบจากการกระทำของ PUT
Marjan Venema

โหวตขึ้นสำหรับคำอธิบายที่ดี, ความปลอดภัยและ idempotency ในส่วนที่เหลือ
roo2

คำอธิบายที่ดี อย่างไรก็ตามคุณสร้างคำสั่งหลาย ๆ อย่างเช่น: "จุดทั้งหมดของ PUT คือการมีผลข้างเคียงนั่นคือการอัพเดตทรัพยากร" ดูเหมือนจะขัดแย้งกันเว้นแต่ว่าคุณหมายถึงบางสิ่งที่แตกต่างจากคำว่า "ผลข้างเคียง" มากกว่า "สิ่งที่สองหรือไม่ตั้งใจที่เกิดขึ้นนอกเหนือจากผลกระทบหลักที่ตั้งใจไว้"
MarredCheese

@MarredCheese: ฉันใช้คำในความหมายการเขียนโปรแกรมมาตรฐานซึ่งโดยทั่วไปหมายถึง "ใด ๆ 'ผล' ที่ไม่ใช่ค่าตอบแทน"
Jörg W Mittag

อ่าแน่นอน ขอขอบคุณสำหรับการชี้แจง.
MarredCheese

1

คุณถูกต้องที่PUT ต้องไม่มีผลข้างเคียงแต่ฉันจะเพิ่มบางสิ่งนี้

PUT ต้องไม่มีผลข้างเคียงกับทรัพยากรที่กำลังดำเนินการ PUT

คุณกำลังอัปเดตpersonทรัพยากรที่ระบุว่าF02E395A235ดังนั้นการใช้ PUT นั้นถูกต้อง ในขณะนี้ตามกฎทางธุรกิจคุณยังติดตามการเปลี่ยนแปลงที่ไม่สามารถมองเห็นได้จากเอนทิตีที่เรียกใช้ (ผู้บริโภคของบริการ REST) สิ่งนี้จะไม่เพิ่มรายการใหม่ในpersonทรัพยากร ภาพรวมเชิงประวัติจะไม่สามารถเข้าถึงได้โดยใช้/person/จุดปลาย ดังนั้นฉันเชื่อว่า PUT ควรเป็นที่ยอมรับอย่างสมบูรณ์ในกรณีนี้


1
ไม่มีผลข้างเคียงกับทรัพยากร แต่จำนวนผลข้างเคียงใด ๆ ในสิ่งอื่น ๆ (เคาน์เตอร์การบันทึกการสืบค้นกลับการตรวจสอบ ... ) เป็นที่ยอมรับอย่างสมบูรณ์
Marjan Venema
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.