เมื่อใดที่ฉันใช้พา ธ พารามิเตอร์เทียบกับพารามิเตอร์คิวรีใน RESTful API


142

ฉันต้องการให้ RESTful API ของฉันสามารถคาดเดาได้มาก แนวทางปฏิบัติที่ดีที่สุดในการตัดสินใจว่าเมื่อใดควรแบ่งกลุ่มข้อมูลโดยใช้ URI แทนที่จะใช้พารามิเตอร์แบบสอบถาม

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


1
มีคำตอบสำหรับคำถามที่คล้ายกันที่นี่ ... stackoverflow.com/questions/3198492/…
— Lalit Mehra

คำตอบ:


246

แนวทางปฏิบัติที่ดีที่สุดสำหรับการออกแบบ RESTful API คือพา ธ พา ธ ใช้เพื่อระบุรีซอร์สหรือรีซอร์สเฉพาะในขณะที่ใช้พารามิเตอร์เคียวรีเพื่อจัดเรียง / กรองทรัพยากรเหล่านั้น

นี่คือตัวอย่าง สมมติว่าคุณกำลังใช้ปลายทาง RESTful API สำหรับเอนทิตีที่เรียกว่า Car คุณจะจัดโครงสร้างจุดสิ้นสุดของคุณดังนี้:

GET /cars
GET /cars/:id
POST /cars
PUT /cars/:id
ลบ/cars/:id

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

ตอนนี้สมมติว่าคุณต้องการเพิ่มความสามารถในการกรองรถยนต์ตามสีในคำขอ GET ของคุณ เนื่องจากสีไม่ใช่ทรัพยากร (เป็นคุณสมบัติของทรัพยากร) คุณสามารถเพิ่มพารามิเตอร์การสืบค้นที่ทำสิ่งนี้ได้ คุณจะเพิ่มพารามิเตอร์การสืบค้นนั้นในคำขอGET/carsของคุณดังนี้:

GET /cars?color=blue

จุดสิ้นสุดนี้จะถูกนำมาใช้เพื่อให้ส่งคืนเฉพาะรถยนต์สีน้ำเงินเท่านั้น

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

อดีต /two-words


3
ขอบคุณสำหรับคำตอบหลังไมค์ นี่เป็นวิธีการที่ชัดเจนและเรียบง่าย คุ้มค่ากับการโหวตจากฉัน ถึงกระนั้นบ่อยครั้งที่นักพัฒนาเลือกใช้แนวทาง 'รถยนต์ / สีน้ำเงิน' ฉันสงสัยว่าเหตุผลของพวกเขาคืออะไร ... บางทีพวกเขาอาจตัดสินใจที่จะสร้างพารามิเตอร์พา ธ สำหรับฟิลด์ที่จำเป็นหรือบางทีพวกเขาอาจทำเพื่อระบุว่า ฐานข้อมูลถูกแบ่งโดยชาร์ดนั้น
— cosbor11

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

3
แล้ว / cars? id = 1 & color = blue แทนรถยนต์ / 1 /? color = blue โดยพื้นฐานแล้วคุณกำลังกรองทรัพยากรรถยนต์ในแต่ละสถานการณ์
— mko

1
ผิดตั้งแต่รถที่มี id 1 มีอยู่คันเดียว แต่รถที่มีสีน้ำเงินอาจมีหลายคัน มีความแตกต่างระหว่างตัวตนและตัวกรอง
— พอล

1
สมมติฐานของฉันที่ว่าทำไมการใช้พา ธ พา ธ จึงแพร่หลายมากเป็นเพราะนักพัฒนาหลายคนได้เรียนรู้จากเฟรมเวิร์กที่ออกแบบโดยผู้ที่ไม่เข้าใจหลักการ REST ที่ดี (โดยเฉพาะ Ruby on Rails)
— Chris Broski

58

วิธีคิดพื้นฐานเกี่ยวกับเรื่องนี้มีดังนี้:

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

ในตัวอย่างข้างต้นรถยนต์เป็นวัตถุที่จับต้องได้มากซึ่งมีคุณลักษณะเช่นยี่ห้อรุ่นและ VIN ซึ่งไม่เคยเปลี่ยนแปลงและสีระบบกันสะเทือน ฯลฯ ที่อาจเปลี่ยนแปลงไปตามกาลเวลา ดังนั้นหากเราเข้ารหัส URI ด้วยแอตทริบิวต์ที่อาจเปลี่ยนแปลงเมื่อเวลาผ่านไป (ชั่วขณะ) เราอาจจบลงด้วย URI หลายรายการสำหรับวัตถุเดียวกัน:

GET /cars/honda/civic/coupe/{vin}/{color=red}

และหลายปีต่อมาหากสีของรถคันเดียวกันนี้เปลี่ยนเป็นสีดำ:

GET /cars/honda/civic/coupe/{vin}/{color=black}

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

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

GET /cars/honda/civic/coupe/{vin}?color={black}

บรรทัดล่าง - คิดว่าพหุสัณฐาน


2
กระบวนทัศน์ที่น่าสนใจ .. นี่คือแพตเทนการออกแบบที่ใช้กันทั่วไป คุณสามารถจัดหา API บางส่วนที่ใช้สิ่งนี้ในเอกสารประกอบหรือข้อมูลอ้างอิงบางส่วนที่สรุปกลยุทธ์นี้ได้หรือไม่
— cosbor11

1
ฉันชอบวิธีที่คุณเน้น "TYPE" เมื่อคุณเขียนว่า "A URI คือตัวระบุทรัพยากรที่ระบุอินสแตนซ์เฉพาะของ TYPE ของทรัพยากร" ฉันคิดว่านั่นเป็นความแตกต่างที่สำคัญ
— jrahhali

15

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

อย่างไรก็ตามฉันคิดว่าคุณไม่ได้สร้าง REST API จริง แต่เป็น API 'REST inspired' (เช่น Google Drive one) ในกรณีเหล่านี้หลักทั่วไปคือ 'path params = resource identification' และ 'query params = resource sorting' ดังนั้นคำถามก็คือคุณสามารถระบุทรัพยากรของคุณโดยไม่ซ้ำกันโดยไม่มีสถานะ / ภูมิภาคได้หรือไม่? ถ้าใช่อาจเป็นพารามิเตอร์การค้นหา ถ้าไม่มีแสดงว่าเป็นพารามิเตอร์พา ธ

HTH


12
ฉันไม่เห็นด้วย API ที่ดีควรคาดเดาได้ สงบหรืออย่างอื่น
— cosbor11

3
ฉันคิดอย่างนั้น ควรมีความคล้องจองและเหตุผลว่า URI ถูกสร้างขึ้นอย่างไรแทนที่จะตั้งชื่อจุดสิ้นสุดโดยพลการ เมื่อเราสามารถเขียนไคลเอนต์ API ได้โดยไม่ต้องอ้างอิงเอกสารอย่างต่อเนื่องแสดงว่าคุณได้เขียน API ที่ดีในความคิดของฉัน
— cosbor11

2
"เมื่อเราสามารถเขียนไคลเอนต์ API ได้โดยไม่ต้องอ้างอิงเอกสาร" นั่นคือสิ่งที่ฉันคิดว่าความเข้าใจของเราเกี่ยวกับ REST แตกต่างกัน ... ไคลเอนต์ API ไม่จำเป็นต้อง 'สร้าง' URL พวกเขาควรเลือกจากการตอบสนองของการเรียก API ก่อนหน้านี้ หากคุณใช้เว็บไซต์เป็นตัวเปรียบเทียบ ... คุณไปที่ facebook.com จากนั้นคุณเลือกลิงก์ไปยังหน้ากิจกรรม คุณไม่สนใจว่า URL เหตุการณ์ของ facebook จะ 'คาดเดาได้' หรือไม่เนื่องจากคุณไม่ได้พิมพ์เข้าไปคุณไปที่นั่นผ่านลิงก์ไฮเปอร์มีเดีย เช่นเดียวกับ REST api ดังนั้นทำให้ URI มีความหมายสำหรับคุณ (เซิร์ฟเวอร์) แต่ไม่ใช่ไคลเอนต์ของคุณ
— Oliver McPhee

2
เพิ่มหมายเหตุ นี่ไม่ได้หมายความว่า URI ไม่ควรเป็นไปตามรูปแบบที่เข้าใจง่ายเพียง แต่หมายความว่าไม่ใช่ข้อ จำกัด ของ RESTful API ปัญหาใหญ่ที่สุดของพื้นที่นี้คือคนที่คิดว่าลูกค้าควรสร้าง URL ขึ้นมาเอง พวกเขาไม่ควรเนื่องจากสร้างการมีเพศสัมพันธ์ระหว่างไคลเอนต์และเซิร์ฟเวอร์ที่ไม่ควรมีอยู่ (เช่น - เซิร์ฟเวอร์ไม่สามารถเปลี่ยน URL ได้โดยไม่ทำลายแอปพลิเคชันไคลเอนต์ทั้งหมด) ใน REST API เซิร์ฟเวอร์สามารถเปลี่ยนแปลงได้ตามที่ต้องการ
— Oliver McPhee

3
+1 สำหรับการใช้คำต่อไปนี้: "'path params = resource identification' และ 'query params = resource sorting'" สิ่งนี้ทำให้ฉันกระจ่างขึ้นจริงๆ
— Doug

3

เมื่อฉันออกแบบ API ทรัพยากรหลักคือpeopleอะไร โดยปกติผู้ใช้จะขอให้กรองpeopleดังนั้นเพื่อป้องกันไม่ให้ผู้ใช้โทรหาบางอย่างเช่น/people?settlement=urbanทุกครั้งฉันจึงใช้งาน/people/urbanซึ่งทำให้ฉันสามารถเพิ่มได้ใน/people/ruralภายหลัง นอกจากนี้ยังอนุญาตให้เข้าถึง/peopleรายการทั้งหมดหากมีการใช้งานในภายหลัง ในระยะสั้นเหตุผลของฉันคือการเพิ่มเส้นทางไปยังส่วนย่อยทั่วไป

จากที่นี่ :

นามแฝงสำหรับข้อความค้นหาทั่วไป

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


1

โดยทั่วไปฉันมักจะใช้พารามิเตอร์เส้นทางเมื่อมี 'ลำดับชั้น' ที่ชัดเจนในทรัพยากรเช่น:

/region/state/42

หากทรัพยากรเดียวนั้นมีสถานะสามารถ:

/region/state/42/status

อย่างไรก็ตามหาก 'ภูมิภาค' ไม่ได้เป็นส่วนหนึ่งของทรัพยากรที่ถูกเปิดเผยจริงๆอาจเป็นหนึ่งในพารามิเตอร์การค้นหาซึ่งคล้ายกับการแบ่งหน้า (ตามที่คุณกล่าวถึง)


0

การแบ่งกลุ่มเป็นลำดับชั้นและ "สวย" แต่สามารถ จำกัด ได้

ตัวอย่างเช่นหากคุณมี URL ที่มีสามส่วนแต่ละส่วนจะส่งผ่านพารามิเตอร์ที่แตกต่างกันเพื่อค้นหารถยนต์ผ่านยี่ห้อรุ่นและสี:

www.example.com/search/honda/civic/blue

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

www.example.com/search?color=blue
www.example.com/search?make=civic

ตอนนี้คุณมีวิธีอ้างอิงค่าผ่านทางคีย์ - ไม่ว่าจะเป็น "color" หรือ "make" ในโค้ดการสืบค้นของคุณ

คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยอาจใช้กลุ่มเพิ่มเติมเพื่อสร้างโครงสร้างค่าคีย์เช่น:

www.example.com/search/make/honda/model/civic/color/blue

หวังว่าคงเข้าท่า ..


-2

ตัวอย่าง URL: /rest/{keyword}

URL นี้เป็นตัวอย่างสำหรับพารามิเตอร์เส้นทาง เราสามารถรับข้อมูล URL นี้ได้โดยใช้@PathParam.

ตัวอย่าง URL: /rest?keyword=java&limit=10

URL นี้เป็นตัวอย่างสำหรับพารามิเตอร์การค้นหา เราสามารถรับข้อมูล URL นี้ได้โดยใช้@Queryparam.

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