Mewakili tindakan (kata kerja) di REST URI

16

Saya memiliki operasi cetak untuk melakukan untuk dokumen pelanggan saya. Saya perlu operasi standar lainnya untuk dilakukan juga, seperti menambah, memperbarui, menghapus. jadi, saya telah mengikuti:

  • Untuk membuat pelanggan baru:
    URI = / customer / {id}, ketik = POST, Methodname = CreateCustomer ()
  • Untuk memperbarui:
    URI: / customer / {id}, ketik = PUT, metode = UpdateCstomer ()
  • Untuk pelanggan Hapus:
    URI = / pelanggan / {id}, ketik = HAPUS, Methodname = DeleteCustomer ()
  • Untuk Tampilan:
    URI: / customer / {id}, ketik = GET, method = GetCustomer ()

Sekarang, jika saya perlu mencetak dokumen untuk pelanggan itu, saya perlu fungsi cetak. URI saya mungkin terlihat seperti ini: / customer / {id}, type = POST, method = PrintCustomer (). Tapi saya telah menggunakan tipe URI dan POST untuk CreateCustomer. Saya ingin URI terlihat seperti ini: / customer / Print / {id}, type = POST, method = PrintCustomer ().

Tetapi saya tidak dapat memiliki kata kerja "Cetak" di URI saya. Apa cara terbaik untuk melakukan ini? Saya memikirkan / pelanggan / dokumen / {id} sebagai URI ... tapi saya akan mengalami masalah yang sama. Saya akan memiliki operasi CRUD pada "dokumen". Jadi, sekali lagi saya kehabisan apa yang akan saya gunakan untuk "cetak". Mohon saran.

Nitya Maha
sumber
2
Pencetakan biasanya merupakan operasi sisi klien, jadi saya ingin tahu - bagaimana pengaturan Anda sehingga mengharuskan Anda untuk mengirim perintah ke server REST?
Shauna
2
@Shauna Belum tentu, URI mungkin merupakan permintaan ke server untuk versi sumber daya yang ramah cetak (yaitu tampilan yang berbeda).
Evan Plaice
1
@ EvanPlaice - Cukup adil, meskipun itu masih menyisakan tindakan mencetak kepada klien (yang, bahkan setelah mengambil versi ramah-cetak sisi-server, kemudian akan memutuskan perangkat mana yang akan dicetak dan mengirim perintah cetak itu sendiri, bahkan jika itu perintah pergi ke server cetak). Permintaan untuk mendapatkan versi sumber daya yang ramah cetak akan secara logis ... baik ... MENDAPATKAN.
Shauna
@Shauna Memicu pekerjaan cetak dari permintaan HTTP saja tidak dimungkinkan karena keamanan browser. Permintaan untuk versi cetak-ramah hanyalah permintaan GET tapi Anda masih perlu cara untuk menentukan bahwa browser harus membuat versi yang dapat dicetak. Anda dapat menentukan URL yang berbeda tetapi itu akan melanggar prinsip-prinsip REST karena Anda sebenarnya tidak meminta sumber daya yang berbeda, hanya transformasi berbeda dari sumber daya yang sama. Karenanya alasan untuk menentukan transformasi melalui parameter-kueri dan / atau tipe konten.
Evan Plaice
Saya tidak memiliki cukup perwakilan untuk dikirim sebagai jawaban, tetapi saya merasa menarik bahwa tyk.io/rest-never-crud berpendapat bahwa itu POST /customers/123/printadalah hal yang sah untuk dilakukan.
jlh

Jawaban:

9

POSTtidak berarti "membuat", itu berarti "proses". Anda dapat membuat sumber daya baru dengan memposting permintaan yang sesuai ke sumber daya yang ada (yaitu mengirim ke /customersuntuk membuat pelanggan baru). Tetapi Anda juga dapat menggunakan POSTuntuk mengisi semua tindakan lain yang tidak sesuai dengan paradigma CRUD yang rapi.

Dalam hal pencetakan, Anda harus mempertimbangkan tindakan mencetak sebagai sumber daya itu sendiri. Anda meminta sistem untuk membuat "pekerjaan cetak" untuk Anda. Ini berarti Anda dapat memiliki prints/sumber daya yang bertindak sebagai wadah untuk semua cetakan yang diminta. Ketika Anda ingin mencetak sesuatu, Anda POSTdokumen untuk sumber daya ini yang berisi semua informasi tentang print-out yang ingin Anda buat, mengidentifikasi sumber daya yang ingin Anda cetak dengan tautan ke sana.

Sebagai dokumen JSON, bisa terlihat seperti ini:

{
   contents: ["http://site/customers/12345"],
   paper-size: "A4",
   duplex: "true"
}

Tentunya, Anda perlu menyesuaikan ini agar relevan dengan apa yang ingin Anda lakukan. Kuncinya adalah Anda mengidentifikasi sumber daya lain untuk dicetak dengan menentukan URL mereka.

Menanggapi permintaan tersebut, Anda dapat dengan mudah mengembalikan a 200 OKatau a 204 No-Contentdan memperlakukannya sebagai proses api-dan-lupa. Namun, jika Anda ingin meningkatkannya, Anda dapat kembali 201 Createddan menentukan URL dari pekerjaan cetak yang baru dibuat, misalnya /prints/12345.

Seorang pengguna kemudian dapat melakukan GETpada sumber daya untuk melihat status pekerjaan cetak mereka (menunggu, dalam proses, dll), atau dapat meminta pekerjaan dibatalkan dengan mengeluarkan a DELETE.

Setelah Anda mengulangi masalah dalam hal sumber daya, desain RESTful harus datang secara alami dan memberi Anda kesempatan untuk memperluas dan meningkatkan dengan cara yang mungkin tidak segera Anda pertimbangkan.

Paul Turner
sumber
2
POST biasanya berarti membuat / menyisipkan, sedangkan put biasanya berarti memperbarui menyimpan / memperbarui. Begitulah didefinisikan dalam REST bahkan jika itu tidak bagaimana biasanya digunakan dalam HTML.
Evan Plaice
2
@EvanPlaice nama spec HTTP PUT sebagai kata kerja buat / perbarui (menggunakan model buat + perbarui alih-alih yang lebih dikenal buat + ambil + pembaruan) dan POST adalah kata kerja "pengolahan data", serta kata kerja "tambahkan" . Roy Fielding dalam blognya menggambarkan POST sebagai kata kerja untuk digunakan ketika Anda tidak ingin menstandardisasi operasi. POST menggunakan semantik "buat" ketika Anda menganggapnya menambahkan item baru ke koleksi item. Dalam hal ini, Tragedi memukul paku di kepala menggunakan POST untuk memproses atau menambahkan pekerjaan cetak.
Rob
@RobY OK, itu masuk akal. Sebagai contoh, PUT dapat digunakan untuk mewakili SPROC yang dirancang untuk memasukkan data ke dalam basis data. Padahal, POST bisa menjadi langkah menengah dan mutasi yang diperlukan untuk mengumpulkan / menyiapkan data itu. Desain operasi POST dapat berubah atau diganti ketika desain berkembang tetapi operasi PUT mewakili model yang (idealnya) tidak boleh berubah. Saya akan memperbarui jawaban saya tetapi yang ini sudah melakukan pekerjaan yang bagus untuk menjelaskan perbedaannya.
Evan Plaice
4

Saya melakukan ini sebelumnya. Untuk mencetak dokumen, saya hanya mengembalikan sumber daya versi pdf. Klien hanya perlu mengirim permintaan GET untuk sumber daya dengan Accept header application / pdf.

Ini juga menghindari membuat URI baru untuk sumber daya sementara seperti pekerjaan cetak. Menggunakan header HTTP juga merupakan bagian dari REST dan menjaga URI tetap bersih.

imel96
sumber
3

Cukup tambahkan parameter ke GET URI saat ini

Cukup umum menggunakan URI untuk beberapa tindakan.

Jika Anda berbicara tentang sumber daya yang sama tetapi tindakan yang berbeda, Anda akan mendefinisikannya sebagai parameter.

/ customer / {id}? print = true

Kemudian di mana Anda menentukan metode GET Anda mendeteksi keberadaan parameter cetak dan menanganinya secara berbeda.

REST didefinisikan dengan cara berikut:

  • POST - Buat catatan, aset, atau sumber daya
  • PUT - Pembaruan, catatan, aset, atau sumber daya
  • HAPUS - Menghapus, mencatat, aset, atau sumber daya

GET, di sisi lain, dimaksudkan untuk digunakan dalam berbagai cara karena biasanya ada banyak bentuk berbeda yang dapat diambil sumber daya. Itu juga mengapa permintaan GET direpresentasikan sebagai string kueri. Jika Anda bekerja dengan sumber daya basis data, Anda benar-benar akan mengambil tampilan melalui kueri tetapi REST sengaja disarikan ke tingkat yang lebih tinggi karena dirancang untuk menangani berbagai jenis sumber daya.

Spesifikasi REST cukup berpikir ke depan, meskipun API baru-baru ini mulai menggunakannya dengan berat.

Jika Anda tertarik untuk mempelajari lebih lanjut tentang protokol REST, saya sangat menyarankan Anda membaca " Haters Gonna Hate HATEOAS ".


Memperbarui:

@Shauna menunjukkan lubang yang menarik dalam penalaran saya. Itu tidak benar cara yang benar dan banyak bentuk yang dianggap dapat diterima. Saya memikirkannya lagi dan karena tujuan penggunaan Anda adalah untuk mentransformasikan data menjadi representasi yang berbeda, masuk akal untuk mendefinisikan transformasi sebagai MIME-Type baru.

Misalnya, Anda dapat mewakili URI sebagai:

/customer/{id}+print

Di mana Anda dapat mengatur respons Content-Type ke teks / html + cetak. Dengan begitu Anda juga akan memiliki opsi untuk mendefinisikan lebih banyak transformasi di masa mendatang.

Sebagai contoh:

// for application/json
/customer/{id}+json

// for application/atom+xml
/customer/{id}+atom

Bagaimanapun, semua bentuk dapat diterima. Implementasi yang Anda putuskan lebih tergantung pada preferensi pribadi, dan kemampuan server Anda.

Selain itu, izinkan saya mengklarifikasi karena tampaknya ada beberapa kebingungan. Parameter-print 'query' dan / atau tipe konten digunakan untuk menentukan bagaimana sumber daya ditransformasikan. Bukan cara memicu pekerjaan cetak fisik. Untuk alasan keamanan, akses tingkat perangkat keras selalu diserahkan kepada pengguna / klien / browser.

Evan Plaice
sumber
Untuk menambahkan - Sebagai alternatif untuk menggunakan string kueri ( ?print=true), Anda juga dapat menggunakan parameter URI (yaitu - /customer/{id}/printable). Yang mana yang Anda gunakan akan sangat tergantung pada standar sistem Anda (CMS, kerangka kerja, kode pada umumnya) diatur untuk menangani. Keduanya dianggap valid dan dapat diterima .
Shauna
@Shauna Secara teknis, pendekatan terbaik adalah dengan menggunakan tipe MIME khusus untuk mencetak dengan URI '/ pelanggan / {id} + cetak' dan respons MIME-Jenis teks / html + cetak. Keuntungan dari pendekatan semacam itu, Anda dapat membuat transformasi untuk banyak tipe-MIME (ex text / html, text / x-markdown, application / json, dll) untuk URI yang sama. Kerugian dari solusi yang Anda sajikan adalah, Anda harus membuat URI tambahan (dan menentukan rute lain) untuk setiap MIME-Type yang berbeda. Ini agak mengalahkan tujuan menggunakan REST.
Evan Plaice
(lanjutan) Saya berpendapat bahwa hacks URI adalah anti-pola yang diperkenalkan terutama oleh komunitas ROR tetapi itu tidak berarti mereka tidak berguna. Dengan kedatangan server HTTPd tingkat rendah yang lebih baik, semakin mudah untuk mengimplementasikan REST dengan cara yang sepenuhnya memanfaatkan potensinya. Banyak hal telah terjadi sejak zaman di mana Apache dan merutekan semuanya melalui index.html adalah satu-satunya pilihan.
Evan Plaice
2
GET seharusnya tidak membuat perubahan keadaan atau memiliki efek samping. Anggap GET idempoten, artinya middleware dapat mencoba kembali permintaan jika tidak melihatnya. Dalam hal ini, setiap percobaan ulang akan menghasilkan salinan dokumen baru yang baru dicetak. ;)
Rob
@RobY Saya berasumsi bahwa tindakan 'mencetak' tidak akan menangani proses pencetakan dokumen secara fisik karena akan lebih baik dilayani oleh browser dan driver cetak. Sebaliknya, media / hasil cetak akan mengembalikan representasi dokumen yang 'ramah cetak'. Karena itu, idempotensi dipertahankan. Poin bagusnya, mengirim pekerjaan cetak di internet tanpa kewarganegaraan akan menjadi waktu yang buruk.
Evan Plaice