แนวคิด REST API


10

ฉันมีคำถามสามข้อเกี่ยวกับการออกแบบ REST API ที่ฉันหวังว่าบางคนสามารถทำให้เข้าใจได้ ฉันค้นหาอย่างไม่ลดละเป็นเวลาหลายชั่วโมง แต่ไม่พบคำตอบสำหรับคำถามของฉันที่ใดก็ได้ (บางทีฉันอาจไม่รู้ว่าต้องค้นหาอะไร)

คำถามที่ 1

คำถามแรกของฉันเกี่ยวกับการกระทำ / RPC ฉันพัฒนา REST API มาระยะหนึ่งแล้วและฉันเคยคิดถึงสิ่งต่าง ๆ ในแง่ของการรวบรวมและทรัพยากร อย่างไรก็ตามฉันได้เจอสองสามกรณีที่กระบวนทัศน์ไม่ได้นำไปใช้และฉันสงสัยว่ามีวิธีที่จะกระทบยอดกับกระบวนทัศน์ REST หรือไม่

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

เหมาะสมไหมที่จะรวมการเรียกการดำเนินการบางอย่างกับ URI ทรัพยากร (เช่น/collection/123?action=resendEmail)? จะเป็นการดีกว่าถ้าระบุการกระทำและส่งรหัสทรัพยากรให้ (เช่น/collection/resendEmail?id=123) นี่เป็นวิธีที่ผิดที่จะเกิดขึ้นหรือไม่? ตามเนื้อผ้า (อย่างน้อยด้วย HTTP) การดำเนินการที่ดำเนินการอยู่เป็นวิธีการร้องขอ (GET, POST, PUT, DELETE) แต่สิ่งเหล่านั้นไม่อนุญาตให้มีการกระทำที่กำหนดเองกับทรัพยากร

คำถามที่ 2

ฉันใช้ส่วนการสอบถามของ URL เพื่อกรองชุดของทรัพยากรที่ส่งคืนเมื่อทำการสืบค้นคอลเลกชัน (เช่น/collection?someField=someval) ภายในตัวควบคุม API ของฉันฉันจะกำหนดชนิดของการเปรียบเทียบที่จะทำกับฟิลด์และค่านั้น ฉันพบว่าสิ่งนี้ใช้งานไม่ได้ ฉันต้องการวิธีที่อนุญาตให้ผู้ใช้ API ระบุประเภทการเปรียบเทียบที่ต้องการดำเนินการ

แนวคิดที่ดีที่สุดที่ฉันมีมาในตอนนี้คืออนุญาตให้ผู้ใช้ API ระบุว่าเป็นส่วนต่อท้ายของชื่อฟิลด์ (เช่น/collection?someField:gte=someval- เพื่อระบุว่าควรคืนทรัพยากรที่someFieldมากกว่าหรือเท่ากับ (> =) อะไรก็ตามที่somevalเป็น นี่เป็นความคิดที่ดีหรือไม่เป็นความคิดที่ไม่ดีถ้าใช่เพราะเหตุใดมีวิธีที่ดีกว่าในการอนุญาตให้ผู้ใช้ระบุประเภทการเปรียบเทียบเพื่อดำเนินการกับเขตข้อมูลและค่าที่กำหนดหรือไม่

คำถามที่ 3

ฉันมักจะเห็น URI ของบางสิ่งบางอย่างที่มีลักษณะเหมือน/person/123/dogsที่จะได้รับsperson dogsฉันมักจะหลีกเลี่ยงบางสิ่งบางอย่างเช่นนั้นเพราะในท้ายที่สุดฉันคิดว่าการสร้าง URI เช่นนั้นจริง ๆ แล้วคุณแค่เข้าถึงdogsคอลเลกชันที่ถูกกรองด้วยpersonรหัสเฉพาะ /dogs?person=123มันจะเทียบเท่ากับ มีเหตุผลที่ดีที่ REST URI จะลึกมากกว่าสองระดับ/collection/resource_idหรือไม่?


10
คุณมีสามคำถาม ทำไมไม่โพสต์แยกกัน?
Anaximander

3
มันจะเป็นการดีกว่าถ้าแบ่งคำถามนี้ออกเป็น 3 คำถาม ผู้ดูอาจสามารถตอบได้อย่างยอดเยี่ยมสำหรับคำถามหนึ่งข้อ แต่ไม่ใช่ทั้งหมด

2
ฉันคิดว่าพวกเขาเกี่ยวข้องกันทั้งหมด ชื่อเป็นระดับสูงเล็กน้อย แต่คำถามนี้จะช่วยให้คนจำนวนมากและพบได้ง่ายในระหว่างการค้นหา SE คำถามนี้ควรกลายเป็น Community Wiki เมื่อมีการเพิ่มการโหวตและเนื้อหาอย่างเพียงพอแล้ว ฉันใช้เวลาหลายสัปดาห์เพื่อค้นคว้าสิ่งนี้
Andrew T Finnell

1
มันอาจเป็นการดีกว่าที่จะโพสต์แยก IDK อย่างไรก็ตามตามที่ @AndrewFinnell พูดถึงฉันคิดว่ามันเป็นความคิดที่ดีที่จะเก็บคำถามไว้ด้วยกันเพราะสิ่งเหล่านี้เป็นคำถามที่เกี่ยวข้องกับ REST ที่ยากที่สุดเท่าที่ฉันเคยมีมาและมันก็ดีสำหรับคนอื่น ๆ ด้วยกัน.
Justin Warkentin

คำตอบ:


11

เหมาะสมไหมที่จะรวมการเรียกการดำเนินการบางอย่างกับ URI ทรัพยากร (เช่น/collection/123?action=resendEmail)? จะเป็นการดีกว่าถ้าระบุการกระทำและส่งรหัสทรัพยากรให้ (เช่น/collection/resendEmail?id=123) นี่เป็นวิธีที่ผิดที่จะเกิดขึ้นหรือไม่? ตามเนื้อผ้า (อย่างน้อยด้วย HTTP) การดำเนินการที่ดำเนินการอยู่เป็นวิธีการร้องขอ (GET, POST, PUT, DELETE) แต่สิ่งเหล่านั้นไม่อนุญาตให้มีการกระทำที่กำหนดเองกับทรัพยากร

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

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

ฉันใช้ส่วนการสอบถามของ URL เพื่อกรองชุดของทรัพยากรที่ส่งคืนเมื่อทำการสืบค้นคอลเลกชัน (เช่น/collection?someField=someval) ภายในตัวควบคุม API ของฉันฉันจะกำหนดชนิดของการเปรียบเทียบที่จะทำกับฟิลด์และค่านั้น ฉันพบว่าสิ่งนี้ใช้งานไม่ได้ ฉันต้องการวิธีที่อนุญาตให้ผู้ใช้ API ระบุประเภทการเปรียบเทียบที่ต้องการดำเนินการ

ความคิดที่ดีที่สุดที่ฉันได้มาด้วยเพื่อให้ห่างไกลคือการอนุญาตให้ผู้ใช้ API เพื่อระบุว่าเป็นรยางค์กับชื่อฟิลด์ (เช่น/collection?someField:gte=someval- เพื่อบ่งชี้ว่าควรกลับทรัพยากรที่ SomeField มากกว่าหรือเท่ากับ ( >=) สิ่งที่somevalเป็น นี่เป็นความคิดที่ดีหรือไม่เป็นความคิดที่ไม่ดีถ้าใช่ทำไมมีวิธีที่ดีกว่าในการอนุญาตให้ผู้ใช้ระบุประเภทการเปรียบเทียบเพื่อดำเนินการกับเขตข้อมูลและค่าที่กำหนดหรือไม่

ฉันอยากจะระบุตัวกรองข้อทั่วไปและมีที่เป็นพารามิเตอร์แบบสอบถามตัวเลือกในคำขอใด ๆ เพื่อดึงเนื้อหาของคอลเลกชัน จากนั้นลูกค้าสามารถระบุวิธี จำกัด การส่งคืนได้อย่างถูกต้องในแบบที่คุณต้องการ ฉันยังกังวลเกี่ยวกับการค้นพบภาษาตัวกรอง / แบบสอบถาม ยิ่งคุณทำมันได้มากเท่าไหร่ก็จะยิ่งทำให้ลูกค้าค้นพบได้ยากขึ้น อีกวิธีหนึ่งซึ่งอย่างน้อยในทางทฤษฎีเกี่ยวข้องกับปัญหาการค้นพบนั้นคือการอนุญาตให้มีการ จำกัด ทรัพยากรย่อยของคอลเลกชันซึ่งลูกค้าได้รับโดยการโพสต์เอกสารอธิบายข้อ จำกัด ของทรัพยากรการเก็บรวบรวม ยังคงเป็นการละเมิดเล็กน้อย แต่อย่างน้อยก็เป็นสิ่งที่คุณสามารถทำให้ค้นพบได้อย่างชัดเจน!

การค้นพบแบบนี้เป็นหนึ่งในสิ่งที่ฉันพบว่ามีความแข็งแรงน้อยที่สุดกับ REST

ฉันมักจะเห็น URI ของที่ดูเหมือนว่า/person/123/dogsจะได้รับสุนัขบุคคล ฉันมักจะหลีกเลี่ยงบางสิ่งบางอย่างเช่นนั้นเพราะในท้ายที่สุดแล้วฉันคิดว่าการสร้าง URI เช่นนั้นจริงๆแล้วคุณแค่เข้าถึงชุดสุนัขที่ถูกกรองด้วยรหัสบุคคลที่เฉพาะเจาะจง /dogs?person=123มันจะเทียบเท่ากับ มีเหตุผลที่ดีที่ REST URI จะลึกมากกว่าสองระดับ/collection/resource_idหรือไม่?

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

คอลเลกชันประเภทอื่น ๆ สามารถสร้างแบบจำลองเป็นการเปลี่ยนเส้นทาง HTTP จึง/person/123/dogsสามารถจริงจะได้รับการตอบสนองด้วยการทำ 307 /dogs?person=123ที่เปลี่ยนเส้นทางไป ในกรณีนี้การรวบรวมไม่ใช่องค์ประกอบของ UML จริง ๆ แต่เป็นการรวม UML ความแตกต่างนั้นสำคัญ มันสำคัญมาก!


2
คุณมีคะแนนรวมที่มั่นคง อย่างไรก็ตามในขณะที่resendEmailการกระทำสามารถจัดการได้โดยการสร้างคอลเลกชันและโพสต์มันดูเหมือนเป็นธรรมชาติน้อยลง ที่จริงแล้วฉันไม่เก็บอะไรไว้ในฐานข้อมูลเมื่อมีการส่งอีเมลอีกครั้ง (ไม่จำเป็น) ไม่มีการแก้ไขทรัพยากรจึงเป็นเพียงการกระทำที่ประสบความสำเร็จหรือล้มเหลว ฉันไม่สามารถส่งคืนรหัสทรัพยากรที่มีอยู่นอกเหนือจากอายุการใช้งานได้ทำให้การดำเนินการดังกล่าวเป็นการแฮ็กแทนที่จะใช้ RESTful มันไม่ใช่การดำเนินการ CRUD
Justin Warkentin

3

เป็นที่เข้าใจได้ว่าจะสับสนเล็กน้อยเกี่ยวกับวิธีการใช้ REST อย่างถูกต้องตามวิธีที่ฉันได้เห็น บริษัท ขนาดใหญ่ออกแบบ REST API ของพวกเขา

คุณถูกต้องใน REST นั้นเป็นระบบการรวบรวมทรัพยากร มันหมายถึงการโอนรัฐตัวแทน ไม่ใช่คำจำกัดความที่ดีถ้าคุณถามฉัน แต่แนวคิดหลักคือ 4 HTTP VERBs และไร้สัญชาติ

สิ่งสำคัญที่ควรทราบคือคุณมี VERBS 4 ตัวที่มี REST เหล่านี้คือ GET, POST, PUT และ DELETE resendตัวอย่างของคุณจะเพิ่มคำกริยาใหม่ไปยัง REST นี่ควรเป็นธงสีแดง

คำถามที่ 1

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

คุณมีตัวเลือกน้อย

REST - วิธีการทำงานตามทรัพยากร

สร้างtasksทรัพยากรที่คุณสามารถส่งงานเฉพาะลงในระบบของคุณเพื่อดำเนินการ จากนั้นคุณสามารถGETทำงานตามภารกิจที่IDส่งคืนเพื่อพิจารณาสถานะของงานนั้น

หรือคุณสามารถมิกซ์ในSOAP over HTTPWeb Service เพื่อเพิ่ม RPC บางอย่างเข้ากับสถาปัตยกรรมของคุณ

การสืบค้นสำหรับงานทั้งหมดสำหรับทรัพยากรเฉพาะ

GET http://server/api/myCollection/123/tasks

{ "tasks" :
    [ { "22333" : "http://server/api/tasks/223333" } ] 
}

ตัวอย่างทรัพยากรงาน

PUT http://server/api/tasks

{ 
    "type" : "send-email" , 
    "parameters" : 
    { 
         "collection-type" : "foo" , 
         "collection-id" : "123" 
    } 
}

==> ส่งคืน id ของภารกิจ

223334

GET http://server/api/tasks/223334

{ 
    "status" : "complete" , 
    "date" : "whenever" 
}

ส่วนที่เหลือ - การใช้ POST เพื่อทริกเกอร์การกระทำ

คุณสามารถPOSTเพิ่มข้อมูลลงในทรัพยากรได้ตลอดเวลา ในความคิดของฉันนี้จะละเมิดวิญญาณของ REST แต่มันจะยังคงเป็นไปตาม

คุณสามารถทำ POST คล้ายกับสิ่งนี้:

POST http://server/api/collection/123

{ "action" : "send-email" }

คุณจะอัปเดตทรัพยากร 123 จากการรวบรวมด้วยข้อมูลเพิ่มเติม ข้อมูลเพิ่มเติมนั้นเป็นสิ่งที่บอกให้แบ็กเอนด์ส่งอีเมลสำหรับทรัพยากรนั้น

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

SOAP - บริการบนเว็บที่ยอมรับทรัพยากรที่ได้รับจาก REST

สร้าง WebService ใหม่ซึ่งคุณสามารถส่งอีเมลตาม ID ทรัพยากรก่อนหน้านี้จาก REST API ฉันจะไม่ไปลงรายละเอียดเกี่ยวกับสบู่ที่นี่เป็นคำถามเดิมเป็นเรื่องเกี่ยวกับการพักผ่อนและทั้งสองแนวคิด / เทคโนโลยีไม่ควรนำมาเปรียบเทียบเป็นมันของแอปเปิ้ลและส้ม

คำถามที่ 2

คุณมีตัวเลือกไม่กี่ตัวที่นี่:

ดูเหมือนว่า บริษัท ขนาดใหญ่จำนวนมากที่เผยแพร่ REST API จะเปิดเผยsearchคอลเลกชันที่เป็นเพียงวิธีการส่งผ่านพารามิเตอร์การสืบค้นเพื่อส่งคืนทรัพยากร

GET http://server/api/search?q="type = myCollection & someField >= someval"

ซึ่งจะส่งคืนชุดทรัพยากร REST ที่มีคุณสมบัติครบถ้วนเช่น:

{
    "results" : 
       { [ 
             "location" : "http://server/api/myCollection/1",
             "location" : "http://server/api/myCollection/9",
             "location" : "http://server/api/myCollection/56"
         ]
       }
}

หรือคุณสามารถอนุญาตบางอย่างเช่นMVELเป็นพารามิเตอร์การสืบค้น

คำถามที่ 3

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

หมายเหตุ

ฉันไม่เห็นด้วยเกี่ยวกับความเห็นที่อ่านได้จากผู้อื่น แม้ว่าสิ่งที่บางคนอาจคิดว่า REST นั้นยังไม่ได้มีไว้สำหรับมนุษย์ มันมีไว้สำหรับการบริโภคเครื่อง หากฉันต้องการดูทวีตของฉันฉันใช้เว็บไซต์ปกติของ Twitters ฉันไม่ได้ใช้ REST GET กับ API ของพวกเขา ถ้าฉันต้องการทำบางสิ่งบางอย่างกับทวีตโดยทางโปรแกรมฉันก็ใช้ REST API ใช่ API ควรเป็นที่เข้าใจได้ แต่สิ่งที่คุณทำgteไม่ดี

อีกสิ่งที่สำคัญกับ REST ก็คือคุณควรเริ่มต้นที่จุดใดก็ได้ใน API ของคุณและไปยังแหล่งข้อมูลอื่น ๆ ที่เกี่ยวข้องโดยไม่ทราบ URL ที่แน่นอนของทรัพยากรอื่น ๆ ล่วงหน้า ผลลัพธ์ของGETVERB ใน REST ควรส่งคืน REST URL แบบเต็มของทรัพยากรที่อ้างอิง ดังนั้นแทนที่จะแบบสอบถามกลับหมายเลขหนึ่งของPersonวัตถุก็จะกลับ URL http://server/api/people/13แบบเต็มที่เช่น จากนั้นคุณสามารถนำทางผลลัพธ์โดยทางโปรแกรมได้แม้ว่าจะเปลี่ยน URL ก็ตาม

การตอบสนองต่อความคิดเห็น

ในโลกแห่งความเป็นจริงมีสิ่งต่าง ๆ ที่จำเป็นต้องเกิดขึ้นซึ่งไม่ได้สร้างอ่านปรับปรุงหรือลบทรัพยากร (CRUD)

สามารถดำเนินการเพิ่มเติมในทรัพยากร ฐานข้อมูลเชิงสัมพันธ์ทั่วไปสนับสนุนแนวคิดของ Stored Procedure เหล่านี้เป็นคำสั่งเพิ่มเติมที่สามารถดำเนินการกับชุดข้อมูล REST ไม่มีแนวคิดโดยเนื้อแท้ และไม่มีเหตุผลที่ควรจะเป็น การกระทำประเภทนี้เหมาะสำหรับ RPC หรือ SOAP Web Services

นี่เป็นปัญหาทั่วไปที่ฉันเห็นด้วย REST API นักพัฒนาซอฟต์แวร์ไม่ชอบข้อ จำกัด ทางแนวคิดที่ล้อมรอบ REST ดังนั้นพวกเขาจึงปรับมันเพื่อทำสิ่งที่พวกเขาต้องการ ที่ทำลายมันจากการเป็นบริการสงบแม้ว่า โดยพื้นฐานแล้ว URL เหล่านั้นจะถูกGETเรียกใช้บนเซิร์ฟเล็ตที่เลียนแบบ REST

คุณมีตัวเลือกน้อย:

  • สร้างทรัพยากรงาน
  • สนับสนุนPOSTข้อมูลเพิ่มเติมไปยังทรัพยากรเพื่อดำเนินการ
  • เพิ่มคำสั่งเพิ่มเติมผ่าน SOAP Web Service

หากคุณใช้พารามิเตอร์การสืบค้นที่ HTTP VERB คุณจะใช้เพื่อส่งอีเมลอีกครั้งหรือไม่

  • GET- สิ่งนี้ส่งอีเมลอีกครั้งและส่งคืนข้อมูลของทรัพยากรหรือไม่ จะเกิดอะไรขึ้นหากระบบแคช URL นั้นและถือว่าเหมือนกับ URL เฉพาะสำหรับทรัพยากรนั้น ทุกครั้งที่พวกเขากด URL มันจะส่งอีเมลอีกครั้ง
  • POST - คุณไม่ได้ส่งข้อมูลใหม่ใด ๆ ไปยังทรัพยากรจริง ๆ แล้วเป็นเพียงพารามิเตอร์การสืบค้นเพิ่มเติม

ขึ้นอยู่กับข้อกำหนดที่ได้รับทั้งหมดการทำPOSTทรัพยากรที่มีaction fieldข้อมูล POST จะช่วยแก้ปัญหาได้


3
ในขณะที่ REST ใช้งานผ่าน HTTP จะให้คำกริยา 4 ตัวแก่คุณฉันไม่เชื่อว่าคำกริยาเหล่านั้นควรจะจบ ในโลกแห่งความเป็นจริงมีสิ่งต่าง ๆ ที่จำเป็นต้องเกิดขึ้นโดยที่ไม่ต้องสร้างอ่านปรับปรุงหรือลบทรัพยากร (CRUD) การส่งอีเมลเป็นอีกสิ่งหนึ่ง ฉันไม่ต้องการจัดเก็บหรือแก้ไขอะไรในฐานข้อมูล มันเป็นการกระทำที่ประสบความสำเร็จหรือล้มเหลว
Justin Warkentin

@JustinWarkentin ฉันเข้าใจว่าความต้องการของคุณคืออะไร แต่นั่นไม่ได้ทำให้ REST เป็นอะไรที่ไม่เป็น การเพิ่มคำกริยาใหม่ไปยัง URL นั้นขัดต่อสถาปัตยกรรม REST ฉันจะอัปเดตคำตอบของฉันเพื่อเสนอทางเลือกอื่นที่จะสงบ
Andrew T Finnell

@JustinWarkentin ลองดู 'REST - การใช้ POST เพื่อกระตุ้นการกระทำ' ในคำตอบของฉัน
Andrew T Finnell

0

คำถามที่ 1:มีความเหมาะสมที่จะรวมการเรียกการดำเนินการบางอย่างกับ URI ของทรัพยากรหรือจะเป็นการดีกว่าที่จะระบุการดำเนินการและส่งรหัสทรัพยากรไปให้หรือไม่

คำถามที่ดี. ในกรณีนี้ฉันแนะนำให้คุณใช้วิธีการหลังคือระบุการดำเนินการและส่งรหัสทรัพยากรให้ วิธีนี้เมื่อทรัพยากรของคุณมีการแก้ไขเป็นครั้งแรกในทางกลับกันมันเรียกการ/sendEmailกระทำ (หมายเหตุด้านข้าง: ไม่จำเป็นต้องเรียกว่า "ส่ง") เป็นคำขอ RESTful แยกต่างหาก (ซึ่งคุณสามารถโทรอีกครั้งในภายหลังและอีกครั้ง )

คำถามที่ 2:เกี่ยวกับการใช้ตัวดำเนินการเปรียบเทียบเช่น:/collection?someField:gte=someval

ในขณะที่เทคนิคนี้ใช้ได้ก็เป็นความคิดที่ไม่ดี หนึ่งในหลักการสำคัญของ REST คือความสามารถในการอ่านได้ ฉันขอแนะนำให้คุณเพียงแค่ส่งโอเปอเรเตอร์การเปรียบเทียบเป็นพารามิเตอร์อื่นตัวอย่างเช่น: /collection?someField=someval&operator=gteและแน่นอนการออกแบบ API ของคุณเพื่อให้เหมาะสำหรับกรณีเริ่มต้น (ในกรณีที่operatorพารามิเตอร์นั้นไม่อยู่ใน URI)

คำถามที่ 3:เคยมีเหตุผลที่ดีที่ REST URI จะลึกกว่าสองระดับหรือไม่?

ได้; สำหรับสิ่งที่เป็นนามธรรม ฉันได้เห็น REST API สองสามตัวที่ใช้เลเยอร์ของสิ่งที่เป็นนามธรรมผ่านหลายระดับ URI ตัวอย่างเช่น: /vehicles/cars/123หรือ/vehicles/bikes/123ในทางกลับกันอนุญาตให้คุณทำงานกับข้อมูลที่เป็นประโยชน์เกี่ยวกับทั้งสอง/vehiclesและ/vehicles/bikesคอลเล็กชัน ต้องบอกว่าฉันไม่ใช่แฟนตัวยงของวิธีนี้ คุณแทบจะไม่ต้องทำสิ่งนี้ในทางปฏิบัติและโอกาสที่คุณจะสามารถออกแบบ API ใหม่เพื่อใช้เพียง 2 ระดับ

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


ฉันคิดว่าตัวอย่างของคำถาม # 2 นั้นง่ายกว่า ฉันจำเป็นต้องระบุตัวดำเนินการเปรียบเทียบสำหรับแต่ละเขตข้อมูลที่ใช้ในการกรองคอลเลกชันไม่ใช่เพียงฟิลด์เดียวดังนั้นในตัวอย่างของคุณมันจะต้องมีลักษณะ/collection?field1=someval&field1Operator=gte&field2=someval&field2Operator=eqดังนี้
Justin Warkentin

0

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

สมมติว่าคุณมีคอนเทนเนอร์ "ค้นหา" ที่นั่นคุณทำPOST /api/searches/กับข้อกำหนดแบบสอบถามในเนื้อหา มันอาจเป็น JSON, XML, หรือแม้แต่เอกสาร SQL สิ่งที่ง่ายสำหรับคุณ หากเคียวรีวิเคราะห์คำถูกต้องการค้นหาใหม่จะถูกสร้างเป็นทรัพยากรใหม่ด้วย URI ของตัวเองสมมติว่า/api/searches/q123/

จากนั้นไคลเอ็นต์สามารถGET /api/searches/q123/เรียกค้นผลลัพธ์ได้

สุดท้ายคุณสามารถขอให้ลูกค้าลบแบบสอบถามหรือลบออกหลังจากปิดเซสชัน


0

มีความเหมาะสมที่จะรวมการเรียกการดำเนินการบางอย่างกับ URI ทรัพยากร (เช่น / collection / 123? action = resendEmail) หรือไม่ จะเป็นการดีกว่าถ้าระบุการดำเนินการและส่งรหัสทรัพยากรให้กับมัน (เช่น / collection / resendEmail? id = 123) นี่เป็นวิธีที่ผิดที่จะเกิดขึ้นหรือไม่? ตามเนื้อผ้า (อย่างน้อยด้วย HTTP) การดำเนินการที่ดำเนินการอยู่เป็นวิธีการร้องขอ (GET, POST, PUT, DELETE) แต่สิ่งเหล่านั้นไม่อนุญาตให้มีการกระทำที่กำหนดเองกับทรัพยากร

ไม่มันไม่เหมาะสมเนื่องจาก IRIs ใช้สำหรับระบุทรัพยากรและไม่ใช่การดำเนินการ (แต่ ppl ใช้วิธีนี้แทนวิธีการในขณะที่ในกรณีที่ไม่สนับสนุนวิธีที่ไม่ใช่ POST และ GET) สิ่งที่คุณสามารถทำได้คือหาวิธี HTTP ที่เหมาะสมหรือสร้างวิธีการใหม่ POST อาจเป็นเพื่อนของคุณในกรณีเหล่านี้ (ppl ใช้ถ้าไม่สามารถหาวิธีที่เหมาะสมและคำขอไม่ได้รับการเรียกคืน) อีกวิธีหนึ่งในการสร้างทรัพยากรจากการส่งอีเมลและPOST /emailsสามารถส่งอีเมลได้โดยไม่ต้องสร้างทรัพยากรจริง Btw โครงสร้าง URI ไม่ได้มีความหมายดังนั้นจากมุมมอง REST มันไม่สำคัญว่าคุณใช้ URIs ประเภทใด สิ่งสำคัญคือ meta-data (เช่นความสัมพันธ์ลิงก์ ) ที่กำหนดให้กับลิงก์ที่คุณส่งไปยังลูกค้า

แนวคิดที่ดีที่สุดที่ฉันมีมาในตอนนี้คืออนุญาตให้ผู้ใช้ API ระบุว่าเป็นส่วนต่อท้ายของชื่อฟิลด์ (เช่น / collection? someField: gte = someval - เพื่อระบุว่าควรคืนทรัพยากรที่ someField มากกว่า หรือเท่ากับ (> =) อะไรก็ตามที่เป็น someval นี่เป็นความคิดที่ดีหรือไม่ถ้าเป็นเช่นนั้นทำไมมีวิธีที่ดีกว่าในการอนุญาตให้ผู้ใช้ระบุประเภทการเปรียบเทียบเพื่อดำเนินการกับเขตข้อมูลและค่าที่กำหนดหรือไม่

คุณไม่จำเป็นต้องสร้างภาษาคิวรีเอง ฉันอยากจะใช้ที่มีอยู่แล้วและเพิ่มคำอธิบายแบบสอบถามบางส่วนไปยังลิงค์ meta-data คุณควรใช้ประเภทสื่อ RDF (เช่น JSON-LD) เพื่อทำเช่นนั้นหรือใช้ประเภท MIME แบบกำหนดเอง (afaik ไม่มีรูปแบบที่ไม่ใช่แบบ RDF ซึ่งสนับสนุนสิ่งนี้) การใช้มาตรฐานที่มีอยู่จะแยกลูกค้าของคุณออกจากเซิร์ฟเวอร์นั่นคือข้อ จำกัด ของอินเทอร์เฟซแบบเดียว

มันจะเทียบเท่ากับ / Dogs? person = 123 มีเหตุผลที่ดีจริง ๆ หรือไม่ที่ REST URI จะลึกเกินสองระดับ (/ collection / resource_id)?

ดังที่ฉันได้กล่าวไปแล้วโครงสร้าง URI ไม่สำคัญจากมุมมอง REST คุณสามารถใช้/x71fd823df2เป็นตัวอย่าง มันยังคงสมเหตุสมผลสำหรับลูกค้าเพราะพวกเขาตรวจสอบ meta-data ที่กำหนดให้กับลิงก์ไม่ใช่โครงสร้าง URI วัตถุประสงค์หลักของ URI คือการระบุทรัพยากร ในมาตรฐาน URI พวกเขาระบุว่าเส้นทางประกอบด้วยข้อมูลแบบลำดับชั้นและแบบสอบถามมีข้อมูลที่ไม่ใช่แบบลำดับชั้น แต่มันอาจเป็นเรื่องส่วนตัวมากว่าอะไรคือลำดับขั้น นั่นเป็นเหตุผลที่คุณพบกับ URI ที่ลึกและหลายระดับด้วยคำสั่งที่ยาว

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

คุณควรอ่านอย่างน้อยข้อ จำกัด REST จากการทำวิทยานิพนธ์ Fielding , มาตรฐาน HTTPและAPI เว็บเจนเนอเรชั่นที่ 3จาก Markus

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