Saya berencana untuk membangun RESTfull API tetapi ada beberapa pertanyaan arsitektur yang membuat beberapa masalah di kepala saya. Menambahkan logika bisnis backend ke klien adalah pilihan yang ingin saya hindari karena memperbarui beberapa platform klien sulit dipertahankan secara real time ketika logika bisnis dapat dengan cepat berubah.
Katakanlah kita memiliki artikel sebagai sumber daya (api / artikel), bagaimana seharusnya kita menerapkan tindakan seperti menerbitkan, membatalkan publikasi, mengaktifkan atau menonaktifkan dan sebagainya, tetapi untuk mencoba membuatnya sesederhana mungkin?
1) Haruskah kita menggunakan api / article / {id} / {action} karena banyak logika backend dapat terjadi di sana seperti mendorong ke lokasi terpencil atau mengubah beberapa properti. Mungkin hal tersulit di sini adalah kita perlu mengirim semua data artikel kembali ke API untuk memperbarui dan pekerjaan multi-pengguna tidak dapat diimplementasikan. Sebagai contoh, editor dapat mengirim data 5 detik yang lebih lama dan menimpa perbaikan yang dilakukan beberapa jurnalis lain 2 detik yang lalu dan tidak ada cara yang bisa saya jelaskan kepada klien ini karena mereka yang mempublikasikan artikel sama sekali tidak terhubung dengan memperbarui konten.
2) Membuat sumber daya baru juga bisa menjadi opsi, api / article- {action} / id, tapi kemudian sumber daya yang dikembalikan tidak akan berupa artikel- {action} tetapi artikel yang saya tidak yakin apakah ini tepat. Juga di kelas kode sisi server artikel menangani pekerjaan yang sebenarnya pada kedua sumber daya dan saya tidak yakin apakah ini bertentangan dengan pemikiran RESTfull
Ada saran yang disambut ..
api/article?action=publish
? Parameter kueri dimaksudkan untuk kasus-kasus seperti itu di mana keadaan sumber daya bergantung pada 'algoritma' (atau tindakan) yang Anda sebutkan. Misalnyaapi/articles?sort=asc
validJawaban:
Saya menemukan praktik yang dijelaskan di sini sangat membantu:
sumber
/article/123/deactivations
untuk membuat permintaan penonaktifan baru untuk artikel 123, server mungkin tidak hanya menonaktifkan sumber daya yang diminta, tetapi sebenarnya menyimpan permintaan penonaktifan saya sehingga saya dapat mengambil statusnya nanti.PUT /gists/:id/star
tidakPOST /gists/:id/star
?Operasi yang menghasilkan perubahan status dan perilaku utama di sisi server seperti tindakan "terbitkan" yang Anda gambarkan sulit untuk dimodelkan secara eksplisit di REST. Solusi yang sering saya lihat adalah menggerakkan perilaku rumit seperti itu secara implisit melalui data.
Pertimbangkan memesan barang melalui API REST yang diekspos oleh pedagang online. Memesan adalah operasi yang kompleks. Beberapa produk akan dikemas dan dikirim, akun Anda akan dikenai biaya, dan Anda akan mendapatkan tanda terima. Anda dapat membatalkan pesanan Anda untuk jangka waktu terbatas dan tentu saja ada jaminan uang kembali penuh yang memungkinkan Anda mengirim kembali produk untuk pengembalian uang.
Alih-alih operasi pembelian yang kompleks, API semacam itu memungkinkan Anda membuat sumber daya baru, pesanan pembelian. Pada awalnya Anda dapat melakukan modifikasi apa pun yang Anda inginkan: menambah atau menghapus produk, mengubah alamat pengiriman, memilih opsi pembayaran lain, atau membatalkan pesanan Anda sekaligus. Anda dapat melakukan semua ini karena Anda belum membeli apa pun, Anda hanya memanipulasi beberapa data di server.
Setelah pesanan pembelian Anda selesai dan masa tenggang Anda berlalu, server mengunci pesanan Anda untuk mencegah perubahan lebih lanjut. Hanya pada saat ini urutan operasi yang rumit dimulai, tetapi Anda tidak dapat mengendalikannya secara langsung, hanya secara tidak langsung melalui data yang Anda tempatkan sebelumnya ke dalam pesanan pembelian.
Berdasarkan uraian Anda, "terbitkan" dapat diterapkan dengan cara ini. Alih-alih mengekspos operasi, Anda menempatkan salinan konsep yang telah Anda ulas dan ingin menerbitkan sebagai sumber daya baru di bawah / terbitkan. Ini menjamin setiap pembaruan berikutnya dari draft tidak akan dipublikasikan bahkan jika operasi penerbitan itu sendiri selesai beberapa jam kemudian.
sumber
Hal semacam ini merupakan tantangan, apa pun yang Anda lakukan, ini adalah masalah yang sangat mirip dengan kontrol sumber terdistribusi (mercurial, git, dll.), Dan solusinya, yang dieja dalam HTTP / ReST, terlihat sedikit mirip.
Andaikata Anda memiliki dua pengguna, Alice dan Bob, keduanya sedang mengerjakan
/articles/lunch
. (untuk kejelasan, responsnya berani)Pertama, alice membuat artikel.
Server tidak membuat sumber daya, karena tidak ada "versi" yang terlampir pada permintaan, (dengan asumsi pengidentifikasi
/articles/{id}/{version}
. Untuk melakukan pembuatan, Alice dialihkan ke url artikel / versi yang akan dibuatnya. Pengguna Alice agen kemudian akan mengajukan kembali permintaan di alamat baru.Dan sekarang artikelnya sudah dibuat. selanjutnya, bob melihat artikel:
Bob melihat ke sana:
Dia memutuskan untuk menambahkan kembaliannya sendiri.
Seperti halnya Alice, Bob dialihkan ke tempat ia akan membuat versi baru.
Akhirnya, Alice memutuskan untuk menambah artikelnya sendiri:
Alih-alih diarahkan kembali seperti biasa, kode status yang berbeda dikembalikan ke klien
409
,, yang memberi tahu Alice bahwa versi yang ia coba cabut telah bercabang. Sumber daya baru dibuat anyways (seperti yang ditunjukkan olehLocation
header), dan perbedaan antara keduanya termasuk dalam badan respons. Alice sekarang tahu bahwa permintaan yang baru saja dibuatnya perlu digabungkan.Semua pengalihan ini terkait dengan semantik
PUT
, yang mengharuskan sumber daya baru dibuat persis di tempat yang diminta oleh garis permintaan. ini juga bisa menghemat siklus permintaan menggunakanPOST
, tetapi kemudian nomor versi harus dikodekan dalam permintaan oleh sihir lain, yang tampaknya kurang jelas bagi saya untuk tujuan ilustrasi, tetapi mungkin masih akan lebih disukai dalam API nyata untuk meminimalkan siklus permintaan / respons.sumber
Berikut adalah contoh lain yang tidak berurusan dengan konten dokumen tetapi lebih dengan keadaan sementara. (Saya menemukan versi - mengingat bahwa, secara umum, setiap versi dapat menjadi sumber daya baru - semacam masalah mudah.)
Katakanlah saya ingin mengekspos layanan yang berjalan pada mesin melalui REST sehingga dapat dihentikan, dimulai, dimulai ulang, dan sebagainya.
Apa pendekatan yang paling tenang di sini? POST / service? Command = restart, misalnya? Atau POST / layanan / negara dengan tubuh, katakanlah, 'berjalan'?
Akan menyenangkan untuk menyusun praktik terbaik di sini dan apakah REST adalah pendekatan yang tepat untuk situasi seperti ini.
Kedua, mari kita asumsikan saya ingin menggerakkan beberapa tindakan dari layanan yang tidak mempengaruhi keadaannya sendiri, melainkan memicu efek samping. Misalnya, layanan mailer yang mengirimkan laporan, dibuat pada saat panggilan, ke sekelompok alamat email.
GET / laporan mungkin merupakan cara untuk mendapatkan salinan laporan sendiri; tetapi bagaimana jika kita ingin mendorong ke sisi server tindakan lebih lanjut seperti mengirim email seperti yang saya katakan di atas. Atau menulis ke database.
Kasus-kasus ini menari di sekitar pembagian aksi sumber daya, dan saya melihat cara-cara menangani mereka dengan cara yang berorientasi REST, tetapi terus terang rasanya seperti sedikit peretasan untuk melakukannya. Mungkin pertanyaan kuncinya adalah apakah REST API harus mendukung efek samping secara umum.
sumber
REST berorientasi pada data dan oleh karena itu sumber daya berfungsi paling baik sebagai "hal-hal" bukan tindakan. Semantik implisit dari metode http; DAPATKAN, PUT, HAPUS, dll berfungsi untuk memperkuat orientasi. POST tentu saja, merupakan pengecualian.
Sumber daya dapat berupa campuran data yaitu. konten artikel; dan metadata yaitu. diterbitkan, dikunci, revisi. Ada banyak cara lain yang memungkinkan untuk mengiris data, tetapi Anda harus melihat seperti apa aliran data pertama-tama untuk menentukan yang paling optimal (jika ada). Misalnya, revisi harus menjadi sumber daya mereka sendiri di bawah artikel seperti yang disarankan TokenMacGuy.
Mengenai implementasi saya mungkin akan melakukan sesuatu seperti apa yang disarankan TockenMacGuy. Saya juga akan menambahkan bidang metadata pada artikel, bukan revisi, seperti 'dikunci' dan 'diterbitkan'.
sumber
Jangan menganggapnya secara langsung memanipulasi keadaan artikel. Alih-alih, Anda memasukkan perintah perubahan yang meminta artikel dibuat.
Anda dapat memodelkan menempatkan dalam urutan perubahan sebagai membuat sumber daya perubahan urutan baru (POST). Ada banyak keuntungan. Misalnya, Anda dapat menentukan tanggal dan waktu di masa mendatang ketika artikel tersebut harus diterbitkan sebagai bagian dari urutan perubahan, dan biarkan server khawatir tentang bagaimana itu diterapkan.
Jika penerbitan bukan proses instan, Anda tidak perlu menunggu sampai selesai sebelum kembali ke klien. Anda hanya mengakui bahwa urutan perubahan telah dibuat dan mengembalikan ID urutan perubahan. Anda kemudian dapat menggunakan URL yang sesuai dengan urutan perubahan itu untuk berbagi status urutan perubahan.
Wawasan utama bagi saya adalah mengenali metafora urutan perubahan ini hanyalah cara lain untuk menggambarkan pemrograman berorientasi objek. Alih-alih sumber daya, kami menyebutnya objek. Alih-alih mengubah pesanan, kami menyebutnya pesan. Salah satu cara untuk mengirim pesan dari A ke B di OO adalah memiliki metode panggilan A pada B. Cara lain untuk melakukannya, terutama ketika A dan B di komputer yang berbeda, adalah untuk memiliki A membuat objek baru, M, dan kirimkan ke B. REST hanya memformalkan proses itu.
sumber
Jika saya memahami Anda dengan benar, saya pikir apa yang Anda miliki lebih merupakan masalah penentuan 'aturan bisnis' daripada masalah teknis.
Fakta bahwa suatu artikel dapat ditimpa dapat diselesaikan dengan memperkenalkan tingkat otorisasi di mana pengguna senior dapat mengganti versi pengguna junior. Juga dengan memperkenalkan versi serta kolom untuk menangkap keadaan artikel (misalnya 'dalam pengembangan', 'final' , dll.), Anda bisa mengatasinya. Anda juga dapat memberi pengguna kemampuan untuk memilih versi yang diberikan baik dengan kombinasi waktu pengiriman dan dengan nomor versi.
Dalam semua kasus di atas, layanan Anda perlu menerapkan aturan bisnis yang Anda tetapkan. Jadi Anda dapat memanggil layanan dengan parameter: userid, artikel, versi, tindakan (di mana versi ini opsional, sekali lagi ini tergantung pada aturan bisnis Anda).
sumber