หากต้องการรวม ID ทรัพยากรในส่วนของข้อมูลหรือมาจาก URI


13

การออกแบบ API เราได้พบกับคำถามว่า PUT payload ควรมี ID ของทรัพยากรที่กำลังอัปเดตหรือไม่

นี่คือสิ่งที่เรามีอยู่ในปัจจุบัน:

PUT /users/123 Payload: {name: "Adrian"}

รหัสเส้นทางของเราจะดึง ID จาก URI และดำเนินการต่อด้วยการอัปเดต

ผู้ใช้คนแรกของ API ของเราตั้งคำถามว่าทำไมเราไม่อนุญาต ID ในส่วนของข้อมูล:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

เหตุผลที่เราไม่อนุญาตเพราะเป็นรหัสซ้ำใน payload และ URI

เมื่อคิดถึงสิ่งนี้อีกแล้วเรากำลังเชื่อมโยงทรัพยากรเข้ากับ URI

หาก URI ไม่มี ID จะต้องแก้ไขส่วนของข้อมูล:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

มีเหตุผลอะไรบ้างที่จะไม่ทำ?

คำตอบ:


14

คุณจะควรคู่เครื่องแบบทรัพยากรตัวบ่งชี้ไปที่ทรัพยากร

เมื่อ REST ถูกนำไปใช้กับ HTTP คุณใช้ GET เพื่อดึงค่าปัจจุบันของทรัพยากรและ PUT เพื่อตั้งค่าใหม่ GET ไม่มีน้ำหนักบรรทุกดังนั้น URI จะต้องระบุทรัพยากร และ PUT จะทำอย่างมีเหตุผลกับ URI เดียวกันและเพย์โหลดควรมีลักษณะเหมือนกับที่คุณต้องการให้ GET ถัดไปกลับมา

คุณสามารถใช้ POST กับ URI ที่แตกต่างกันได้ แต่จะมีความหมายน้อยกว่าเนื่องจาก GET ไม่สมมาตรโดยไม่จำเป็น POST ไปยัง URI ทั่วไปนั้นเหมาะสมสำหรับการสร้างทรัพยากรใหม่ ( POST /users/new, payload:, {name: "Adrian"}response {id: 345, name: "Adrian"}) แต่นั่นไม่ใช่ idempotentดังนั้นควรหลีกเลี่ยง หากคุณกำลังดิ้นรนเพื่อ REST¹ คุณควรจอง ID ด้วยการโทรเพียงครั้งเดียวจากนั้นใช้ PUT เพื่อตั้งค่า ID ใหม่ นั่นคือการป้องกันข้อผิดพลาดเพราะหากคำขอแรกล้มเหลวการจอง ID สามารถหมดเวลาในที่สุดและPUTidempotent หรือใช้ UUID ที่ไคลเอ็นต์สร้างขึ้น


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


3
เท่าที่ฉันรู้คำขอ POST ไม่จำเป็นต้อง idempotent ดังนั้นฉันจึงเห็นว่าไม่มีปัญหากับการโพสต์/users(ไม่จำเป็นต้องเพิ่ม 'ใหม่')
lex82

ขอบคุณสำหรับการตอบกลับของคุณ. ฉันเห็นว่ามันเป็นคุณสมบัติที่ดีที่มี idempotency สำหรับคำขอทั้งหมด แต่ใครบอกว่านี่เป็นสิ่งจำเป็นสำหรับ REST API แน่นอนว่า APIs จำนวนมากที่เรียกตัวเองว่า RESTful อนุญาตการร้องขอ POST ที่ไม่ใช่ idempotent (โดยเฉพาะเมื่อเซิร์ฟเวอร์สร้างรหัสสำหรับทรัพยากรใหม่) แต่แม้ว่าคุณจะใช้คำจำกัดความที่เข้มงวดมากของ REST แต่ฉันไม่เห็นว่าข้อ จำกัด ทางสถาปัตยกรรมใดที่ละเมิดกับ POST ที่ไม่ใช่ idempotent เช่นตัวอย่างด้านบน
lex82

ฉันสามารถนึกภาพ POST ที่ละเมิดข้อ จำกัด ได้อย่างแน่นอน ฉันไม่เห็นว่าทำไมการโพสต์ทรัพยากรลงในคอลเลกชันและปล่อยให้เซิร์ฟเวอร์ตัดสินใจบน id ของมันเป็นการละเมิดข้อ จำกัด ของ REST
lex82

ขอให้เรายังคงอภิปรายนี้ในการแชท
lex82

3
แนวคิดทั้งหมดของ POST ไม่ควรเป็น idempotent ....
EralpB

2

เมื่อคิดถึงสิ่งนี้อีกแล้วเรากำลังเชื่อมโยงทรัพยากรเข้ากับ URI

หาก URI ไม่มี ID จะต้องแก้ไขส่วนของข้อมูล:

PUT / no / id / here น้ำหนักบรรทุก: {ชื่อ: "Adrian"} <ผู้ใช้รายใด ???

มีเหตุผลอะไรบ้างที่จะไม่ทำ?

คำตอบสำหรับคำถามนี้ขึ้นอยู่กับว่าคุณต้องการอนุญาตให้ลูกค้าเปลี่ยน ID หรือไม่?

หากไคลเอ็นต์สามารถเปลี่ยน ID ผ่าน PUT ดังนั้น URI สำหรับทรัพยากรจะเปลี่ยนไปและคุณควรให้ 301 Moved อย่างถาวรทุกครั้งที่ทรัพยากรเข้าถึง URI เก่า

ตัวอย่างเช่นคุณเริ่มต้นด้วยทรัพยากรที่

/users/123

และไคลเอนต์ใส่ต่อไปนี้ลงในทรัพยากร

{id: 222, name: "Adrian"}

ทรัพยากรได้รับการปรับปรุงและ URI ของมันคือตอนนี้

/users/222

Locationข้อมูลในการตอบสนองใส่ควรมี URI ใหม่และถ้าคุณไปที่/users/123คุณควรจะได้รับ301การตอบสนองกับชี้ข้อมูลสถานที่ตั้งใหม่/users/222ทรัพยากร

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

หากคุณต้องการให้ URI อื่นใช้ทรัพยากรเดียวกันพูด

/users/adian_lync

ถ้าทรัพยากรนั้นไม่มีเซิร์ฟเวอร์ควรสร้างและสร้างและรหัสเมื่อมันทำ


1
เหตุผลที่เราถามตำแหน่งของ ID ในส่วนของข้อมูลนั้นเป็นเพราะ Backbone.js ผ่าน ID ในคำขอ PUT ตามค่าเริ่มต้น เราสามารถหยุดมันไม่ให้เกิดขึ้น แต่ตอนนี้ฉันอยากรู้ว่าทำไมมันถึงเป็นพฤติกรรมเริ่มต้น
Adrian Lynch

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