Operasi non-CRUD dalam layanan RESTful

106

Apa cara "RESTful" untuk menambahkan operasi non-CRUD ke layanan RESTful? Katakanlah saya memiliki layanan yang memungkinkan akses CRUD ke catatan seperti ini:

GET /api/car/123           <- Returns information for the Car object with ID 123
POST /api/car              <- Creates a new car (with properties in the request)
PUT /api/car/123           <- Updates car 123 (with properties in the request)
DELETE /api/car/123        <- Deletes car 123    
POST /api/car/123/wheel/   <- Creates a wheel and associates it to car 123

Jika saya ingin mengubah warna mobil, saya akan melakukannya POST /api/car/123 dan menyertakan variabel POST untuk warna baru.

Tapi katakanlah saya ingin membeli mobil, dan pengoperasian itu lebih rumit daripada sekadar memperbarui properti "mobil milik" catatan "pengguna". Apakah tenang untuk melakukan sesuatu seperti POST /api/car/123/purchase, di mana "pembelian" pada dasarnya adalah nama metode? Atau haruskah saya menggunakan kata kerja HTTP khusus, sepertiPURCHASE bukan POST?

Atau apakah operasi non-CRUD sama sekali di luar cakupan REST?

MikeWyatt
sumber
5
Jika Anda mengubah warna mobil, akan lebih baik menggunakan PATCH /api/car/123dan mengirimkan parameter warna ATAU gunakan PUT /api/car/123dan kirim seluruh objek mobil. POST akan menyimpulkan bahwa Anda sedang membuat mobil baru dan mungkin tidak boleh menyertakan id di akhir URL
RonnyKnoxville

Jawaban:

65

Pikirkan tentang pembelian sebagai entitas bisnis atau sumber daya dalam kamus RESTful. Meskipun demikian, melakukan pembelian sebenarnya menciptakan sumber daya baru. Begitu:

POST /api/purchase

akan membuat pesanan baru. Detail (pengguna, mobil, dll.) Harus direferensikan oleh id (atau URI) di dalam konten yang dikirim ke alamat ini.

Tidak masalah bahwa memesan mobil bukan hanya INSERT sederhana di database. Sebenarnya, REST bukan tentang mengekspos tabel database Anda sebagai operasi CRUD. Dari sudut pandang logis Anda membuat pesanan (pembelian), tetapi sisi server bebas untuk melakukan sebanyak mungkin langkah pemrosesan yang diinginkan.

Anda bahkan dapat menyalahgunakan protokol HTTP lebih jauh. Gunakan Locationtajuk untuk mengembalikan tautan ke pesanan yang baru dibuat, pilih kode respons HTTP dengan cermat untuk memberi tahu pengguna tentang masalah (sisi server atau klien), dll.

Tomasz Nurkiewicz
sumber
3
REST adalah tentang memanipulasi keadaan sumber daya dan setiap operasi bisnis harus dipetakan untuk menyatakan operasi CRUD. Jika Anda memerlukan semantik operasi bisnis yang keras , Anda harus menggunakan SOAP (SOAP sebenarnya adalah penyampaian pesan, tetapi biasanya diatur dalam operasi respons-permintaan).
Tomasz Nurkiewicz
23
Desain "beli sebagai sumber daya" terlihat rapi. Bagaimana jika sumber daya adalah "bir" .. dan saya ingin server meminumnya .. (ini untuk saya, saya pasti akan MENDAPATKANnya;)) .. haruskah kita mempertimbangkan "tindakan minum" sebagai sumber daya ?! .. atau apakah "minum bir", operasi bisnis yang sulit ?! Lebih serius lagi, apakah desain
RESTful
2
Bagaimana cara Anda mengungkap "setujui pesanan pembelian" melalui layanan REST? Saya pikir @TomaszNurkiewicz benar karena apa pun yang tidak dapat dilakukan dengan rapi dengan cara CRUD akan membutuhkan operasi-semantik yang disediakan oleh SOAP. Kecuali "persetujuan pesanan pembelian" adalah model / entitas itu sendiri. Misalnya POST / persetujuan po (dengan rincian PO dalam permintaan).
mydoghasworms
2
Dari sudut pandang klien REST "menyetujui pesanan pembelian" seharusnya hanya pembaruan pesanan. Misalnya, ubah "Disetujui" menjadi "benar" dan kirim pembaruan ke server. Server mungkin perlu melakukan banyak pemeriksaan dan mungkin perlu memperbarui / membuat banyak sumber daya lain. Tapi itu masalah server dan tidak boleh terlihat oleh klien.
AVee
2
@antinome: "Misalkan klien mengetahui sebagian dari ini", jika itu kasus Anda tidak melakukan REST (mungkin masih valid, software yang masuk akal!). REST dirancang untuk dapat membuat klien yang tidak mengetahui hal semacam itu, untuk membuat klien yang masih berfungsi jika perilaku server berubah. Apa yang Anda coba lakukan adalah RPC klasik, Anda perlu meninjau pendekatan Anda agar sesuai dengan REST, atau menerima bahwa Anda melakukan RPC dan menggunakan protokol yang ditujukan untuk RPC seperti SOAP. REST berusaha keras untuk tidak menjadi RPC, jadi tidak akan pernah cocok saat Anda menginginkan / membutuhkan RPC.
AVee
15

Cara tenang yang saya pahami adalah Anda tidak memerlukan kata kerja HTTP baru, ada kata benda di suatu tempat yang akan berarti apa yang perlu Anda lakukan.

Beli mobil? Bukan begitu

POST /api/order
djna
sumber
2
Bukankah PUT digunakan untuk memperbarui sumber daya karena itu idempoten? Ini berarti Anda dapat meneleponnya sebanyak yang Anda inginkan, tetapi hanya panggilan pertama / terakhir yang penting. POST di sisi lain digunakan untuk membuat sumber daya dan memanggilnya dua kali seharusnya benar-benar membuat dua.
Tomasz Nurkiewicz
1
@Tomas, ya, salah ketik. Prinsip itu penting, kita berurusan dengan hal baru, urutan, tidak perlu kata kerja baru.
djna
5

Apa yang sebenarnya Anda lakukan adalah membuat pesanan. Jadi tambahkan sumber daya lain untuk memesan dan memposting dan meletakkannya di sana selama proses pemesanan.

Pikirkan dalam hal sumber daya daripada pemanggilan metode.

Untuk menyelesaikan pesanan Anda mungkin akan POST / api / order // menyelesaikan atau yang serupa.

Andrew Kothmann
sumber
3

Saya merasa REST API membantu dalam lebih banyak cara daripada hanya menyediakan semantik. Jadi tidak dapat memilih gaya RPC hanya karena beberapa panggilan yang tampaknya lebih masuk akal dalam gaya operasi RPC. Contohnya adalah api google maps untuk menemukan arah antara dua tempat. Tampak seperti ini: http://maps.googleapis.com/maps/api/directions/json?origin=Jakkur&destination=Hebbal

Mereka bisa menyebutnya "findDirections" (kata kerja) dan memperlakukannya sebagai operasi. Sebaliknya mereka menjadikan "direction" (kata benda) sebagai sumber daya dan memperlakukan arah pencarian sebagai kueri pada sumber daya arah (Meskipun secara internal tidak ada sumber daya nyata yang disebut arah dan dapat diimplementasikan oleh logika bisnis untuk menemukan arah berdasarkan parameter).

Maruthi
sumber
Itu contoh yang buruk. Dalam hal ini, arah (semua arah yang memungkinkan, jumlahnya tidak terbatas) adalah sumber daya dan parameternya hanyalah filter. Tetapi Anda tidak dapat melakukan "pembelian" dengan ini, karena filter hanya masuk akal pada operasi get dan menempatkan pesanan atau membatalkannya adalah operasi yang mengubah data
Tseng
2
pembelian akan menjadi POST ke / pesanan dengan json di tubuh untuk menunjukkan pesanan dibuat. cancel akan menjadi PUT ke / order dengan json yang membawa perubahan status order untuk menunjukkan ini adalah pembaruan idempoten. Saya masih mengalami operasi yang tidak dapat diekspresikan dalam format sumber daya. Jadi ingin sekali melihat contoh seperti itu
Maruthi