Kapan saya menggunakan params jalur vs paritas permintaan di API RESTful?

141

Saya ingin membuat API TENANG saya sangat mudah diprediksi. Apa praktik terbaik untuk memutuskan kapan harus melakukan segmentasi data menggunakan URI daripada menggunakan params kueri.

Masuk akal bagi saya bahwa parameter sistem yang mendukung pagination, sorting, dan pengelompokan setelah '?' Tetapi bagaimana dengan bidang seperti 'status' dan 'wilayah' atau atribut lain yang mengelompokkan koleksi Anda? Jika itu juga harus params kueri, apa aturan praktis mengetahui kapan harus menggunakan path params?

cosbor11
sumber
1
pertanyaan serupa dijawab di sini ... stackoverflow.com/questions/3198492/…
Lalit Mehra

Jawaban:

239

Praktik terbaik untuk desain API RESTful adalah bahwa params jalur digunakan untuk mengidentifikasi sumber daya atau sumber daya tertentu, sementara parameter kueri digunakan untuk mengurutkan / memfilter sumber daya tersebut.

Ini sebuah contoh. Misalkan Anda menerapkan titik akhir API RESTful untuk entitas yang disebut Mobil. Anda akan menyusun titik akhir Anda seperti ini:

GET /cars
GET /cars/:id
POST /cars
PUT /cars/:id
DELETE/cars/:id

Dengan cara ini Anda hanya menggunakan parameter jalur saat menentukan sumber daya yang akan diambil, tetapi ini tidak mengurutkan / memfilter sumber daya dengan cara apa pun.

Sekarang anggaplah Anda ingin menambahkan kemampuan untuk memfilter mobil berdasarkan warna dalam permintaan GET Anda. Karena warna bukan sumber daya (ini adalah properti dari sumber daya), Anda bisa menambahkan parameter kueri yang melakukan ini. Anda akan menambahkan parameter permintaan itu ke permintaan GET/cars Anda seperti ini:

DAPATKAN /cars?color=blue

Titik akhir ini akan diterapkan sehingga hanya mobil biru yang akan dikembalikan.

Sejauh menyangkut sintaksis, nama URL Anda harus semuanya huruf kecil. Jika Anda memiliki nama entitas yang umumnya dua kata dalam bahasa Inggris, Anda akan menggunakan tanda hubung untuk memisahkan kata-kata, bukan huruf unta.

Ex. /two-words

Mike
sumber
3
Terima kasih atas jawaban Anda, Mike. Ini adalah metodologi yang jelas dan sederhana; bernilai suara dari saya. Namun, seringkali, pengembang memilih pendekatan 'mobil / biru', saya bertanya-tanya apa alasan mereka melakukannya ... mungkin mereka memutuskan untuk membuat params jalur untuk bidang yang wajib, atau mungkin mereka melakukannya untuk menunjukkan bahwa database dipartisi oleh pecahan itu.
cosbor11
1
Saya tidak yakin apa alasan mereka. Jujur, saya tidak setuju dengan itu. Saya pikir mengikuti konvensi dan menjaganya agar tetap sederhana masuk akal. Dengan melakukannya, Anda memungkinkan konsumen API Anda untuk lebih memahami dengan tepat apa yang harus mereka lakukan untuk mengakses fungsionalitasnya.
Mike
3
bagaimana dengan / mobil? id = 1 & warna = biru bukan mobil / 1 /? warna = biru. Anda pada dasarnya menyaring sumber daya mobil di setiap skenario
mko
1
Salah karena mobil dengan id 1 hanya ada satu tetapi mobil dengan warna biru mungkin banyak. Ada perbedaan antara identitas dan filter
paul
1
Hipotesis saya mengapa menggunakan jalur params begitu luas adalah karena banyak pengembang belajar dari kerangka kerja yang dirancang oleh orang-orang yang tidak memiliki pemahaman yang baik tentang prinsip-prinsip REST (khususnya Ruby on Rails.)
Chris Broski
58

Cara mendasar untuk memikirkan hal ini adalah sebagai berikut:

URI adalah pengidentifikasi sumber daya yang secara unik mengidentifikasi contoh spesifik dari TIPE sumber daya. Seperti semua hal lain dalam hidup, setiap objek (yang merupakan turunan dari beberapa jenis), memiliki serangkaian atribut yang entah waktu-invarian atau temporal.

Dalam contoh di atas, mobil adalah objek yang sangat nyata yang memiliki atribut seperti make, model, dan VIN - yang tidak pernah berubah, dan warna, suspensi, dll. Yang mungkin berubah seiring waktu. Jadi jika kita menyandikan URI dengan atribut yang dapat berubah dari waktu ke waktu (temporal), kita mungkin berakhir dengan beberapa URI untuk objek yang sama:

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

Dan bertahun-tahun kemudian, jika warna mobil yang sama ini diubah menjadi hitam:

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

Perhatikan bahwa instance mobil itu sendiri (objek) tidak berubah - itu hanya warna yang berubah. Memiliki beberapa URI yang menunjuk ke instance objek yang sama akan memaksa Anda untuk membuat beberapa penangan URI - ini bukan desain yang efisien, dan tentu saja tidak intuitif.

Karena itu, URI hanya boleh terdiri dari bagian-bagian yang tidak akan pernah berubah dan akan terus mengidentifikasi sumber daya tersebut secara unik sepanjang masa pakainya. Segala sesuatu yang dapat berubah harus disediakan untuk parameter kueri, seperti:

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

Intinya - pikirkan polimorfisme.

Kingz
sumber
2
Paradigma yang menarik .. Apakah ini pola desain yang umum digunakan? Bisakah Anda memberikan beberapa API yang menggunakan ini dalam dokumentasi mereka atau beberapa referensi yang menguraikan strategi ini?
cosbor11
1
Saya suka bagaimana Anda menekankan "JENIS" ketika Anda menulis "A URI adalah pengidentifikasi sumber daya yang secara unik mengidentifikasi contoh spesifik dari JENIS sumber daya". Saya pikir itu perbedaan penting.
jrahhali
15

Di REST API, Anda seharusnya tidak terlalu khawatir dengan URI yang dapat diprediksi. Saran dari prediktabilitas URI menyinggung kesalahpahaman arsitektur RESTful. Ini mengasumsikan bahwa klien harus membangun URI sendiri, yang seharusnya tidak harus dilakukan.

Namun, saya berasumsi bahwa Anda tidak membuat API REST yang sebenarnya, tetapi API yang 'diilhami REST' (seperti Google Drive). Dalam kasus ini aturan praktisnya adalah 'path params = identifikasi sumber daya' dan 'query params = pengurutan sumber daya'. Jadi, pertanyaannya menjadi, bisakah Anda mengidentifikasi sumber daya Anda secara unik TANPA status / wilayah? Jika ya, maka mungkin ini adalah parameter kueri. Jika tidak, maka ini adalah param path.

HTH.

Oliver McPhee
sumber
11
Saya tidak setuju, API yang baik harus dapat diprediksi; Tenang atau sebaliknya.
cosbor11
3
Aku pikir begitu. Harus ada sajak dan alasan bagaimana URI dibentuk, alih-alih menamai titik akhir secara sewenang-wenang. Ketika seseorang dapat secara intuitif menulis klien API tanpa terus-menerus merujuk dokumentasi, Anda telah menulis API yang bagus menurut saya.
cosbor11
2
"Ketika seseorang dapat secara intuitif menulis klien API tanpa terus-menerus merujuk dokumentasi". Di situlah menurut saya pemahaman kami tentang REST berbeda ... klien API seharusnya tidak perlu 'membuat' URL. Mereka harus memilihnya dari respons panggilan API sebelumnya. Jika Anda menggunakan situs web sebagai analogi ... Anda membuka facebook.com, maka Anda memilih tautan ke halaman acara. Anda tidak peduli apakah URL acara facebook 'dapat diprediksi', saat Anda tidak mengetiknya. Anda sampai di sana melalui tautan hypermedia. Hal yang sama berlaku untuk api REST. Jadi, buatlah URI bermakna bagi Anda (server), tetapi tidak untuk klien
Oliver McPhee
2
Catatan tambahan. Ini tidak berarti bahwa URI tidak harus mengikuti pola yang mudah dipahami, itu hanya berarti bahwa itu bukan kendala dari API tenang. Masalah terbesar dengan area ini adalah orang yang berasumsi bahwa klien harus membuat URL sendiri. Mereka tidak boleh, karena itu menciptakan hubungan antara klien dan server yang seharusnya tidak ada. (misalnya - server tidak dapat mengubah URL tanpa merusak semua aplikasi klien). Dalam REST API, server dapat mengubahnya sesuai keinginan.
Oliver McPhee
3
+1 untuk menggunakan kata-kata berikut: "'jalur params = identifikasi sumber daya' dan 'kueri params = penyortiran sumber daya'". Ini sangat jelas bagi saya.
Doug
3

Setelah saya merancang API sumber daya utama itu people. Biasanya pengguna akan meminta difilter peoplesehingga, untuk mencegah pengguna memanggil sesuatu seperti /people?settlement=urbansetiap kali, saya menerapkannya /people/urbanyang kemudian memungkinkan saya untuk dengan mudah menambahkan /people/rural. Ini juga memungkinkan untuk mengakses /peopledaftar lengkap jika nanti dapat digunakan. Singkatnya, alasan saya adalah menambahkan jalur ke himpunan bagian umum

Dari sini :

Alias ​​untuk pertanyaan umum

Untuk membuat pengalaman API lebih menyenangkan bagi konsumen rata-rata, pertimbangkan untuk mengemas serangkaian kondisi menjadi jalur RESTful yang mudah diakses. Misalnya, permintaan tiket yang baru saja ditutup di atas dapat dikemas sebagaiGET /tickets/recently_closed

Mario Gil
sumber
1

Secara umum, saya cenderung menggunakan parameter path ketika ada 'hierarki' yang jelas di sumber daya, seperti:

/region/state/42

Jika sumber daya tunggal itu memiliki status, seseorang dapat:

/region/state/42/status

Namun, jika 'wilayah' tidak benar-benar bagian dari sumber daya yang diekspos, itu mungkin termasuk sebagai salah satu parameter kueri - mirip dengan pagination (seperti yang Anda sebutkan).

morsor
sumber
0

Segmentasi lebih hierarkis dan "cantik" tetapi bisa membatasi.

Misalnya, jika Anda memiliki url dengan tiga segmen, masing-masing melewati parameter berbeda untuk mencari mobil melalui merek, model, dan warna:

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

Ini adalah url yang sangat cantik dan lebih mudah diingat oleh pengguna akhir, tetapi sekarang jenis Anda terjebak dengan struktur ini. Katakanlah Anda ingin membuatnya sehingga dalam pencarian pengguna dapat mencari SEMUA mobil biru, atau SEMUA Honda Civic? Parameter kueri memecahkan ini karena memberikan pasangan nilai kunci. Jadi Anda bisa lulus:

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

Sekarang Anda memiliki cara untuk referensi nilai melalui kunci itu - baik "warna" atau "membuat" dalam kode kueri Anda.

Anda bisa menyiasatinya dengan kemungkinan menggunakan lebih banyak segmen untuk membuat semacam struktur nilai kunci seperti:

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

Harapan itu masuk akal ..

webmaster_sean
sumber
-2

URL contoh: /rest/{keyword}

URL ini adalah contoh untuk parameter jalur. Kami bisa mendapatkan data URL ini dengan menggunakan @PathParam.

URL contoh: /rest?keyword=java&limit=10

URL ini adalah contoh untuk parameter kueri. Kami bisa mendapatkan data URL ini dengan menggunakan @Queryparam.

Sujithrao
sumber