Saya mencari cara yang masuk akal untuk mewakili pencarian sebagai URL yang tenang.
Pengaturan: Saya punya dua model, Mobil dan Garasi, di mana Mobil bisa di Garasi. Jadi url saya terlihat seperti:
/car/xxxx
xxx == car id
returns car with given id
/garage/yyy
yyy = garage id
returns garage with given id
Mobil bisa ada sendiri (karenanya / mobil), atau bisa ada di garasi. Apa cara yang tepat untuk mewakili, katakanlah, semua mobil di garasi tertentu? Sesuatu seperti:
/garage/yyy/cars ?
Bagaimana dengan penyatuan mobil di garasi yyy dan zzz?
Apa cara yang tepat untuk mewakili pencarian mobil dengan atribut tertentu? Katakan: tunjukkan semua sedan biru dengan 4 pintu:
/car/search?color=blue&type=sedan&doors=4
atau seharusnya / mobil saja?
Penggunaan "pencarian" tampaknya tidak pantas di sana - apa cara / istilah yang lebih baik? Haruskah hanya:
/cars/?color=blue&type=sedan&doors=4
Haruskah parameter pencarian menjadi bagian dari PATHINFO atau QUERYSTRING?
Singkatnya, saya mencari panduan untuk desain url REST lintas-model, dan untuk pencarian.
[Pembaruan] Saya suka jawaban Justin, tapi dia tidak membahas kasus pencarian multi-bidang:
/cars/color:blue/type:sedan/doors:4
atau semacam itu. Bagaimana kita pergi?
/cars/color/blue
ke beberapa kasus lapangan?
/cars
dan/car
tidak semantik dan karena itu ide yang buruk. Selalu gunakan jamak ketika ada lebih dari satu item di bawah kategori itu.Jawaban:
Untuk pencarian, gunakan querystrings. Ini sangat tenang:
Keuntungan dari querystrings reguler adalah standar dan dipahami secara luas dan dapat dihasilkan dari formulir.
sumber
/cars?color=whatever
./cars?color=blue&type=sedan&doors=4/engines
akan berfungsi/cars?param=value
adalah untuk pemfilteran sederhana pada daftar mobil dan/cars/search?param=value
untuk membuat pencarian (dengan ou tanpa persisten) di mana hasilnya mungkin berisi skor pencarian, kategorisasi, dll. Anda juga dapat membuat / menghapus seperti pencarian yang bernama/cars/search/mysearch
. Lihat itu: stackoverflow.com/a/18933902/1480391The tenang desain URL cantik adalah tentang menampilkan sumber daya berdasarkan struktur (direktori-seperti struktur, tanggal: artikel / 2005/5/13, objek dan atribut itu, ..), garis miring
/
menunjukkan struktur hirarkis, gunakan-id
sebagai gantinya.Struktur hierarkis
Secara pribadi saya lebih suka:
Jika pengguna menghapus
/car-id
bagian, itu membawacars
pratinjau - intuitif. Pengguna tahu persis di mana pohon itu berada, apa yang ia lihat. Dia tahu dari pandangan pertama, bahwa garasi dan mobil berhubungan./car-id
juga menunjukkan bahwa itu milik bersama tidak seperti/car/id
.Mencari
Permintaan pencarian tidak apa-apa , hanya ada preferensi Anda, apa yang harus diperhitungkan. Bagian yang lucu muncul ketika bergabung dengan pencarian (lihat di bawah).
Atau pada dasarnya apa pun yang bukan garis miring seperti yang dijelaskan di atas.
Rumus:,
/cars[?;]color[=-:]blue[,;+&]
* meskipun saya tidak akan menggunakan&
tanda karena tidak dapat dikenali dari teks pada pandangan pertama.Daftar opsi
fitur yang mungkin?
Negasikan string pencarian (!)
Untuk mencari mobil apa pun, tetapi tidak hitam dan merah :
?color=!black,!red
color:(!black,!red)
Pencarian yang tergabung
Cari mobil merah atau biru atau hitam dengan 3 pintu di garasi id 1..20 atau 101..103 atau 999 tetapi tidak 5
/garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
Anda dapat membuat kueri pencarian yang lebih kompleks. (Lihatlah CSS3 atribut yang cocok untuk gagasan pencocokan substring. Misalnya mencari pengguna yang mengandung "bar"
user*=bar
.)Kesimpulan
Anyway, ini mungkin menjadi bagian paling penting bagi Anda, karena Anda dapat melakukannya namun Anda seperti setelah semua, hanya perlu diingat bahwa tenang URI merupakan struktur yang mudah dipahami misalnya direktori-seperti
/directory/file
,/collection/node/item
, tanggal/articles/{year}/{month}/{day}
.. Dan ketika Anda menghilangkan salah satu segmen terakhir, Anda langsung tahu apa yang Anda dapatkan.Jadi .., semua karakter ini dibiarkan tanpa kode :
a-zA-Z0-9_.-~
Biasanya diizinkan dikodekan dan tidak, kedua penggunaan kemudian setara.
$-_.+!*'(),
;/?:@=&
Dapat digunakan tanpa kode untuk tujuan yang mereka wakili, jika tidak mereka harus dikodekan.
tidak aman:
<>"#%{}|\^~[]`
Mengapa tidak aman dan mengapa lebih baik dikodekan: RFC 1738 lihat 2.2
Lihat juga RFC 1738 # halaman-20 untuk kelas karakter lainnya.
RFC 3986 lihat 2.2
Terlepas dari apa yang saya katakan sebelumnya, berikut adalah perbedaan umum dari pembatas, yang berarti bahwa beberapa " lebih penting" dari yang lain.
:/?#[]@
!$&'()*+,;=
Lebih banyak bacaan:
Hierarki: lihat 2.3 , lihat 1.2.3
parameter jalan sintaks parameter
pencocokan CSS3 atribut
IBM: RESTful Web services - Dasar-dasar
Catatan: RFC 1738 telah diperbarui oleh RFC 3986
sumber
POST
. Juga, ide-ide lain yang Anda berikan dalam jawaban Anda juga sangat dihargai. Terima kasih banyak!;
dibandingkan dengan&
keterbacaan? Karena jika demikian, saya pikir saya sebenarnya akan memilih&
pembatas yang lebih umum ... bukan? :) terima kasih!&
sebagai pembatas hanya diketahui oleh pengembang. Orang tua, kakek-nenek, dan populasi yang tidak berpendidikan menerima pembatas sebagaimana digunakan dalam teks tertulis umum.Meskipun memiliki parameter di jalur memiliki beberapa keunggulan, ada, IMO, beberapa faktor yang lebih penting.
Tidak semua karakter yang dibutuhkan untuk permintaan pencarian diizinkan dalam URL. Sebagian besar tanda baca dan karakter Unicode harus dikodekan URL sebagai parameter string kueri. Saya bergulat dengan masalah yang sama. Saya ingin menggunakan XPath di URL, tetapi tidak semua sintaks XPath kompatibel dengan jalur URI. Jadi untuk jalur sederhana,
/cars/doors/driver/lock/combination
akan lebih tepat untuk menemukancombination
elemen ' ' di dokumen XML pintu pengemudi. Tetapi/car/doors[id='driver' and lock/combination='1234']
tidak begitu ramah.Ada perbedaan antara memfilter sumber daya berdasarkan salah satu atributnya dan menentukan sumber daya.
Misalnya, sejak
/cars/colors
mengembalikan daftar semua warna untuk semua mobil (sumber daya yang dikembalikan adalah kumpulan objek warna)/cars/colors/red,blue,green
akan mengembalikan daftar objek warna yang merah, biru atau hijau, bukan koleksi mobil.Untuk mengembalikan mobil, jalannya adalah
/cars?color=red,blue,green
atau/cars/search?color=red,blue,green
Parameter di jalur lebih sulit dibaca karena pasangan nama / nilai tidak terisolasi dari sisa jalur, yang bukan pasangan nama / nilai.
Satu komentar terakhir. Saya lebih suka
/garages/yyy/cars
(selalu jamak) daripada/garage/yyy/cars
(mungkin itu salah ketik dalam jawaban asli) karena itu menghindari mengubah jalan antara tunggal dan jamak. Untuk kata-kata dengan 's' yang ditambahkan, perubahannya tidak terlalu buruk, tetapi berubah/person/yyy/friends
menjadi/people/yyy
rumit.sumber
Untuk memperluas jawaban Peter - Anda dapat menjadikan Cari sumber daya kelas satu:
Sumber daya pencarian akan memiliki bidang untuk warna, membuat model, status garasi, dll dan dapat ditentukan dalam XML, JSON, atau format lainnya. Seperti sumber daya Mobil dan Garasi, Anda dapat membatasi akses ke Pencarian berdasarkan otentikasi. Pengguna yang sering menjalankan Pencarian yang sama dapat menyimpannya di profil mereka sehingga mereka tidak perlu dibuat kembali. URL akan cukup pendek sehingga dalam banyak kasus mereka dapat dengan mudah diperdagangkan melalui email. Penelusuran yang disimpan ini dapat menjadi dasar dari umpan RSS khusus, dan sebagainya.
Ada banyak kemungkinan untuk menggunakan Pencarian saat Anda menganggapnya sebagai sumber daya.
Idenya dijelaskan lebih terinci dalam Railscast ini .
sumber
Jawaban Justin mungkin adalah cara yang harus ditempuh, walaupun dalam beberapa aplikasi mungkin masuk akal untuk mempertimbangkan pencarian tertentu sebagai sumber daya sendiri, seperti jika Anda ingin mendukung pencarian yang disimpan bernama:
atau
sumber
Saya menggunakan dua pendekatan untuk mengimplementasikan pencarian.
1) Kasing paling sederhana, untuk menanyakan elemen terkait, dan untuk navigasi.
Ini berarti, permintaan mobil yang memiliki ID garasi sama dengan 1.
Dimungkinkan juga untuk membuat pencarian yang lebih kompleks:
Mobil di semua garasi di FirstStreet yang tidak berwarna merah (halaman ke-3, 100 elemen per halaman).
2) Kueri kompleks dianggap sebagai sumber daya reguler yang dibuat dan dapat dipulihkan.
Badan POST untuk pembuatan pencarian adalah sebagai berikut:
Berbasis di Grails (kriteria DSL): http://grails.org/doc/2.4.3/ref/Domain%20Classes/createCriteria.html
sumber
Ini bukan REST. Anda tidak dapat menentukan URI untuk sumber daya di dalam API Anda. Navigasi sumber daya harus digerakkan oleh hypertext. Tidak apa-apa jika Anda menginginkan URI yang cantik dan kopling dalam jumlah besar, tetapi jangan menyebutnya REST, karena secara langsung melanggar batasan arsitektur RESTful.
Lihat artikel ini oleh penemu REST.
sumber
Meskipun saya menyukai respons Justin, saya merasa itu lebih akurat mewakili filter daripada pencarian. Bagaimana jika saya ingin tahu tentang mobil dengan nama yang dimulai dengan cam?
Cara saya melihatnya, Anda bisa membangunnya ke cara Anda menangani sumber daya tertentu:
/ mobil / cam *
Atau, Anda bisa menambahkannya ke filter:
/ mobil / pintu / 4 / nama / cam * / warna / merah, biru, hijau
Secara pribadi, saya lebih suka yang terakhir, namun saya sama sekali bukan ahli REST (setelah pertama kali mendengarnya sekitar 2 minggu lalu ...)
sumber
/cars?name=cam*
RESTful tidak merekomendasikan penggunaan kata kerja di URL's / cars / search tidak nyenyak. Cara yang tepat untuk memfilter / mencari / paginate API Anda adalah melalui Parameter Kueri. Namun mungkin ada kasus ketika Anda harus melanggar norma. Misalnya, jika Anda mencari di beberapa sumber, maka Anda harus menggunakan sesuatu seperti / search? Q = query
Anda dapat mengunjungi http://saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices/ untuk memahami praktik terbaik untuk merancang API RESTful
sumber
Selain itu saya juga menyarankan:
Di sini,
Search
dianggap sebagai sumber daya anakCars
.sumber
Ada banyak opsi bagus untuk kasus Anda di sini. Anda tetap harus mempertimbangkan menggunakan tubuh POST.
String kueri sempurna untuk contoh Anda, tetapi jika Anda memiliki sesuatu yang lebih rumit, misalnya daftar panjang item atau persyaratan boolean yang sewenang-wenang, Anda mungkin ingin mendefinisikan posting sebagai dokumen, yang dikirim klien melalui POST.
Ini memungkinkan deskripsi pencarian yang lebih fleksibel, serta menghindari batas panjang URL Server.
sumber
Saran saya adalah ini:
Edit:
Semoga itu memberi Anda ide. Pada dasarnya API Istirahat Anda harus mudah ditemukan dan memungkinkan Anda untuk menelusuri data Anda. Keuntungan lain dengan menggunakan URL dan bukan string kueri adalah Anda dapat memanfaatkan mekanisme caching asli yang ada di server web untuk lalu lintas HTTP.
Berikut ini tautan ke halaman yang menjelaskan kejahatan string kueri di REST: http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
Saya menggunakan cache Google karena halaman normal tidak berfungsi untuk saya di sini juga tautan itu: http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
sumber
/cars/colors/red,blue,green
dan/cars/colors/green,blue,red
? Elemen jalur URI harus hierarkis, dan saya tidak benar-benar melihat hal itu terjadi di sini. Saya pikir ini adalah situasi di mana query-string adalah pilihan yang paling tepat.