การดำเนินการที่ไม่ใช่ CRUD ในบริการ RESTful


106

วิธี "RESTful" ในการเพิ่มการดำเนินการที่ไม่ใช่ CRUD ไปยังบริการ RESTful คืออะไร สมมติว่าฉันมีบริการที่อนุญาตให้ CRUD เข้าถึงบันทึกเช่นนี้:

GET /api/car/123           <- Returns information for the Car object with ID 123
POST /api/car              <- Creates a new car (with properties in the request)
PUT /api/car/123           <- Updates car 123 (with properties in the request)
DELETE /api/car/123        <- Deletes car 123    
POST /api/car/123/wheel/   <- Creates a wheel and associates it to car 123

ถ้าฉันต้องการเปลี่ยนสีรถฉันก็แค่POST /api/car/123ใส่ตัวแปร POST สำหรับสีใหม่

แต่สมมติว่าฉันต้องการซื้อรถและการดำเนินการนั้นซับซ้อนกว่าการอัปเดตทรัพย์สิน "รถที่เป็นเจ้าของ" ของ "ผู้ใช้" เป็นเรื่องที่น่ายินดีหรือไม่ที่จะทำอะไรบางอย่างเช่นPOST /api/car/123/purchaseโดยที่คำว่า "ซื้อ" เป็นชื่อวิธีการเป็นหลัก หรือฉันควรใช้กริยา HTTP ที่กำหนดเองเช่นPURCHASEแทนPOST?

หรือการดำเนินการที่ไม่ใช่ CRUD อยู่นอกขอบเขตของ REST หรือไม่


5
หากคุณกำลังเปลี่ยนสีรถควรใช้PATCH /api/car/123และส่งพารามิเตอร์สีหรือใช้PUT /api/car/123และส่งวัตถุรถทั้งหมด POST จะอนุมานได้ว่าคุณกำลังสร้างรถคันใหม่และไม่ควรใส่รหัสที่ท้าย URL
RonnyKnoxville

คำตอบ:


65

ลองนึกถึงการซื้อในฐานะองค์กรธุรกิจหรือทรัพยากรในพจนานุกรม RESTful ที่กล่าวมาการซื้อเป็นการสร้างทรัพยากรใหม่ ดังนั้น:

POST /api/purchase

จะทำการสั่งซื้อใหม่ รายละเอียด (ผู้ใช้รถยนต์ ฯลฯ ) ควรอ้างอิงโดย id (หรือ URI) ภายในเนื้อหาที่ส่งไปยังที่อยู่นี้

ไม่สำคัญว่าการสั่งซื้อรถไม่ใช่แค่ INSERT ธรรมดา ๆ ในฐานข้อมูล ที่จริงแล้ว REST ไม่ได้เกี่ยวกับการเปิดเผยตารางฐานข้อมูลของคุณว่าเป็นการดำเนินการ CRUD จากมุมมองเชิงตรรกะคุณกำลังสร้างคำสั่งซื้อ (ซื้อ) แต่ฝั่งเซิร์ฟเวอร์มีอิสระที่จะทำขั้นตอนการประมวลผลได้มากเท่าที่ต้องการ

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


3
REST เป็นข้อมูลเกี่ยวกับการจัดการสถานะของทรัพยากรและการดำเนินธุรกิจทุกอย่างจะต้องถูกจับคู่กับการดำเนินการ CRUD ของรัฐ หากคุณต้องการความหมายในการดำเนินธุรกิจอย่างหนักคุณจะต้องไปทาง SOAP (SOAP คือการส่งผ่านข้อความ แต่โดยทั่วไปจะจัดระเบียบในการดำเนินการตอบสนองคำขอ)
Tomasz Nurkiewicz

23
การออกแบบ "ซื้อเป็นทรัพยากร" ดูเรียบร้อย จะเป็นอย่างไรถ้าทรัพยากรนั้นเป็น "เบียร์" .. และฉันต้องการให้เซิร์ฟเวอร์ดื่มมัน .. (สำหรับฉันฉันจะได้รับมันอย่างแน่นอน;)) .. เราควรพิจารณา "การกระทำของเครื่องดื่ม" เป็นทรัพยากร ?! .. หรือว่า "ดื่มเบียร์" ธุรกิจหนัก ?! อย่างจริงจังมากขึ้นการออกแบบ RESTful เกี่ยวกับการพิจารณาการกระทำเป็นทรัพยากรหรือไม่! ..
Myobis

2
คุณจะเปิดเผย "อนุมัติใบสั่งซื้อ" ผ่านบริการ REST ได้อย่างไร ฉันคิดว่า @TomaszNurkiewicz ถูกต้องในสิ่งที่ไม่สามารถทำได้อย่างเรียบร้อยในวิธี CRUD จะต้องใช้ความหมายการดำเนินการที่ SOAP จัดเตรียมไว้ เว้นแต่ "การอนุมัติใบสั่งซื้อ" จะเป็นแบบ / นิติบุคคลด้วยตัวมันเอง เช่นการอนุมัติ POST / po (พร้อมรายละเอียด PO ในคำขอ)
mydoghasworms

2
จากมุมมองของลูกค้า REST "อนุมัติใบสั่งซื้อ" น่าจะเป็นการอัปเดตคำสั่งซื้ออีกครั้ง เช่นเปลี่ยน "Approved" เป็น "true" และส่งการอัปเดตไปยังเซิร์ฟเวอร์ เซิร์ฟเวอร์อาจจะต้องทำการตรวจสอบจำนวนมากและอาจต้องอัปเดต / สร้างทรัพยากรอื่น ๆ อีกมากมาย แต่นั่นเป็นปัญหาของเซิร์ฟเวอร์และลูกค้าไม่ควรมองเห็น
AVee

2
@antinome: "สมมติว่าลูกค้ารู้บางส่วนของสิ่งนี้" หากเป็นกรณีที่คุณไม่ได้ทำ REST (อาจยังเป็นซอฟต์แวร์ที่ถูกต้องและสมเหตุสมผล!) REST ได้รับการออกแบบมาเพื่อให้สามารถสร้างไคลเอนต์ที่ไม่รู้จักสิ่งนั้นเพื่อสร้างไคลเอนต์ที่ยังคงใช้งานได้หากพฤติกรรมของเซิร์ฟเวอร์เปลี่ยนไป สิ่งที่คุณกำลังพยายามทำคือ RPC แบบคลาสสิกคุณต้องทบทวนแนวทางของคุณจึงจะเหมาะสมกับ REST หรือยอมรับว่าคุณกำลังทำ RPC และใช้โปรโตคอลที่มีไว้สำหรับ RPC เช่น SOAP REST พยายามอย่างมากที่จะไม่เป็น RPC ดังนั้นมันจะไม่เหมาะสมเมื่อคุณต้องการ / ต้องการ RPC
AVee

15

วิธีที่น่าสนใจอย่างที่ฉันเข้าใจก็คือคุณไม่ต้องการคำกริยา HTTP ใหม่มีคำนามที่ไหนสักแห่งที่จะหมายถึงสิ่งที่คุณต้องทำ

ซื้อรถ? ไม่อย่างนั้น

POST /api/order

2
ไม่ใช้ PUT เพื่ออัปเดตทรัพยากรเนื่องจากเป็น idempotent? ซึ่งหมายความว่าคุณสามารถโทรติดต่อได้หลายครั้งตามที่คุณต้องการ แต่เฉพาะการโทรครั้งแรก / ครั้งสุดท้ายเท่านั้นที่สำคัญ ในทางกลับกัน POST ใช้เพื่อสร้างทรัพยากรและการเรียกมันสองครั้งควรสร้างสองอย่าง
Tomasz Nurkiewicz

1
@ โทมัสใช่พิมพ์ผิด หลักการมีความสำคัญเรากำลังเผชิญกับสิ่งใหม่คำสั่งไม่จำเป็นต้องใช้คำกริยาใหม่
djna

5

สิ่งที่คุณกำลังทำจริงๆคือการสร้างคำสั่งซื้อ ดังนั้นให้เพิ่มทรัพยากรอื่นสำหรับการสั่งซื้อและโพสต์และวางไว้ที่นั่นในระหว่างกระบวนการสั่งซื้อ

คิดในแง่ของทรัพยากรมากกว่าการเรียกใช้เมธอด

ในการสรุปคำสั่งซื้อคุณอาจ POST / api / order // complete หรือคล้าย ๆ กัน


3

ฉันรู้สึกว่า REST API ช่วยได้หลายวิธีมากกว่าแค่การให้ความหมาย ดังนั้นจึงไม่สามารถเลือกสไตล์ RPC ได้เพียงเพราะการเรียกบางอย่างที่ดูเหมือนจะเข้าท่ากว่าในสไตล์การทำงานของ RPC ตัวอย่างคือ google maps api เพื่อค้นหาเส้นทางระหว่างสองสถานที่ มีลักษณะดังนี้: http://maps.googleapis.com/maps/api/directions/json?origin=Jakkur&destination=Hebbal

พวกเขาสามารถเรียกมันว่า "findDirections" (คำกริยา) และถือว่าเป็นการดำเนินการ แต่พวกเขาสร้าง "ทิศทาง" (คำนาม) เป็นทรัพยากรและถือว่าการค้นหาทิศทางเป็นข้อความค้นหาในทรัพยากรทิศทาง (แม้ว่าภายในจะไม่มีทรัพยากรจริงที่เรียกว่าทิศทางและสามารถนำไปใช้โดยตรรกะทางธุรกิจเพื่อค้นหาทิศทางตามพารามิเตอร์)


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

2
การซื้อจะเป็นการโพสต์ถึง / สั่งซื้อโดยมี json ในตัวเพื่อระบุว่ามีการสร้างคำสั่งซื้อ การยกเลิกจะเป็น PUT to / order โดย json ที่มีการเปลี่ยนแปลงสถานะคำสั่งซื้อเพื่อระบุว่าเป็นการอัปเดตที่ไม่ได้ใช้งาน ฉันยังคงต้องเผชิญกับการดำเนินการที่ไม่สามารถแสดงในรูปแบบทรัพยากรได้ ดังนั้นจะต้องอยากเห็นตัวอย่างเช่นนั้น
Maruthi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.