menggunakan PUT dengan efek samping yang dapat diterima (REST)

9

Saya ingin membuat riwayat undo setiap kali pengguna memperbarui formulir. Karena ini adalah pembaruan, saya ingin menggunakan permintaan PUT. Namun, saya membaca bahwa PUT tidak perlu memiliki efek samping .

Apakah bisa diterima menggunakan PUT di sini? Apakah ada alternatif yang lebih baik?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

Di server

doPut('person/:personId',
   // create a new person snapshot
)

Edit:

Riwayat akan terlihat oleh pengguna, menelepon beberapa kali akan menghasilkan banyak versi.

Solusinya adalah memeriksa apakah versinya unik sebelum membuatnya.

roo2
sumber

Jawaban:

11

Orang-orang yang merancang HTTP / 2 jauh lebih bertele-tele tentang ide-ide mereka tentang apa yang harus dilakukan HTTP, sambil tetap mempertahankan makna lama. Mari kita lihat apa yang dikatakan draf spesifikasi HTTP / 2 tentang idempotensi:

4.2.2. Metode Idempoten

Metode permintaan dianggap "idempoten" jika efek yang dituju pada server dari beberapa permintaan yang identik dengan metode itu sama dengan efek untuk satu permintaan seperti itu. metode idempoten.

Seperti definisi safe, properti idempotent hanya berlaku untuk apa yang telah diminta oleh pengguna; server bebas untuk mencatat setiap permintaan secara terpisah, mempertahankan riwayat kontrol revisi, atau menerapkan efek samping non-idempoten lainnya untuk setiap permintaan idempoten .

The efek dimaksudkan pada server untuk setiap permintaan PUT tersebut adalah untuk memperbarui sumberdaya yang diidentifikasi oleh URI . Inilah yang terjadi dalam kasus Anda.

Anda memutuskan untuk versi sumber daya tidak terlalu penting di sini. Jika Anda tidak ingin membuat versi baru ketika tidak ada yang berubah, Anda harus membandingkan muatan dalam permintaan PUT dengan versi sumber daya terbaru (atau diidentifikasi), dan ketika tidak ada properti yang berubah Anda dapat memilih untuk tidak membuat versi baru .


Hasil edit Anda:

Riwayat akan terlihat oleh pengguna, menelepon beberapa kali akan menghasilkan banyak konversi

Sejauh menyangkut sumber daya, itu tidak ada efek samping . Sumber daya di URI itu tidak berubah (properti yang sama mendapatkan PUT). Sejarah hanyalah metadata, karena kemungkinan besar diminta oleh URI yang berbeda atau dengan header permintaan yang berbeda.

CodeCaster
sumber
Terkecuali karena Anda menjawab masalah spesifik saya: "apakah dapat diterima PUT untuk membuat riwayat yang dapat dilihat pengguna", Dan beri saya solusi, terima kasih
roo2
Untuk masalah apa itu solusi? Bahwa timeproperti diperbarui? Saya pikir itu juga metadata, meskipun ada di sumber daya.
CodeCaster
1
Masalahnya adalah bahwa jika beberapa PUT dikirimkan, pengguna akan mendapatkan riwayat undo yang panjang dengan informasi yang berlebihan. memeriksa keunikan memecahkan itu
roo2
12

HTTP membedakan antara dua properti:

  • Idempotensi
  • Keamanan

Idempotensi didefinisikan oleh spek sebagai berikut:

Metode juga dapat memiliki properti " idempotence " di mana (selain dari kesalahan atau masalah kedaluwarsa) efek samping dari N> 0 permintaan identik adalah sama seperti untuk satu permintaan. Metode GET, HEAD, PUTdan DELETEberbagi properti ini. Juga, metode OPTIONSdan TRACE TIDAK HARUS memiliki efek samping, dan karenanya inheren idempoten.

Dan keamanan:

Secara khusus, konvensi telah ditetapkan bahwa metode GETdan TIDAK HARUS memiliki signifikansi mengambil tindakan selain pengambilan. Metode-metode ini harus dianggap " aman ". Ini memungkinkan agen pengguna untuk mewakili metode lain, seperti , dan , dengan cara khusus, sehingga pengguna dibuat sadar akan fakta bahwa tindakan yang mungkin tidak aman sedang diminta.HEADPOSTPUTDELETE

Secara alami, tidak mungkin untuk memastikan bahwa server tidak menghasilkan efek samping sebagai akibat dari melakukan GETpermintaan; pada kenyataannya, beberapa sumber daya dinamis menganggap itu sebagai fitur. Perbedaan penting di sini adalah bahwa pengguna tidak meminta efek samping, sehingga tidak dapat dimintai pertanggungjawaban atas efek sampingnya.

Perhatikan bahwa keselamatan menyiratkan idempotensi: jika suatu metode tidak memiliki efek samping, maka melakukannya berkali-kali akan menghasilkan efek samping yang sama seperti melakukannya sekali, yaitu tidak ada.

Ini menempatkan metode ke dalam tiga kategori:

  • aman (dan dengan demikian juga idempoten): GET, HEAD, OPTION,TRACE
  • idempoten tapi belum tentu aman: PUT,DELETE
  • tidak idempoten atau aman: POST

PUT perlu memiliki sisi yang tidak terpengaruh.

Itu salah. PUTidempoten tetapi tidak aman. The Inti dari PUTadalah memiliki efek samping, yaitu memperbarui sumber daya. Apa yang dimaksud dengan idempotensi adalah bahwa memperbarui sumber daya yang sama dengan konten yang sama beberapa kali harus memiliki efek yang sama dengan memperbarui hanya sekali.

Perhatikan paragraf terakhir di bagian tentang keselamatan [penekanan tambang]:

Secara alami, tidak mungkin untuk memastikan bahwa server tidak menghasilkan efek samping sebagai akibat dari melakukan GETpermintaan; pada kenyataannya, beberapa sumber daya dinamis menganggap itu sebagai fitur. Perbedaan penting di sini adalah bahwa pengguna tidak meminta efek samping, sehingga tidak dapat dimintai pertanggungjawaban atas efek sampingnya .

Meskipun kalimat ini berbicara tentang GETdan keamanan, kita dapat mengasumsikan bahwa penulis juga bermaksud menerapkan alasan PUTdan idempotensi yang sama. TKI: PUTseharusnya hanya memiliki satu efek samping yang terlihat pengguna , yaitu memperbarui sumber daya yang disebutkan. Ini mungkin memiliki efek samping lain, tetapi pengguna tidak bertanggung jawab untuk itu.

Misalnya, fakta yang PUTidempoten berarti bahwa saya dapat mencoba kembali sesering yang saya inginkan: spec menjamin bahwa mengeksekusinya berkali-kali akan persis sama dengan mengeksekusinya sekali. Sangat valid untuk membuat backlog revisi lama sebagai efek samping dari beberapa PUTpermintaan tersebut. Namun, jika, sebagai hasil dari beberapa percobaan ulang, database Anda dipenuhi dengan tumpukan revisi lama, itu bukan masalah saya, itu milik Anda.

TKI: Anda diizinkan memiliki efek samping sebanyak yang Anda inginkan, tetapi

  1. itu harus melihat ke pengguna seolah-olah permintaan mereka idempoten
  2. Anda bertanggung jawab atas efek samping tersebut, bukan pengguna
Jörg W Mittag
sumber
Yap, idempotency adalah tentang status sumber daya yang dimasukkan, bukan tentang status server / layanan lain yang dipengaruhi oleh tindakan PUT.
Marjan Venema
Terpilih untuk penjelasan, keselamatan dan idempotensi dalam Rest
roo2
Penjelasan yang bagus. Namun, Anda membuat beberapa pernyataan seperti ini: "Inti dari PUT adalah memiliki efek samping, yaitu memperbarui sumber daya." Itu tampak seperti kontradiksi kecuali jika Anda mengartikan sesuatu yang berbeda dengan istilah "efek samping" dari "sesuatu yang sekunder atau tidak disengaja yang terjadi di samping efek utama yang dimaksudkan."
MarredCheese
@ MarsredCheese: Saya menggunakan istilah dalam arti pemrograman standar, yang pada dasarnya berarti "hasil 'apa pun yang bukan nilai kembali".
Jörg W Mittag
Ah, tentu saja. Terimakasih atas klarifikasinya.
MarredCheese
1

Anda benar bahwa PUT tidak perlu memengaruhi , namun saya akan menambahkan sesuatu untuk ini.

PUT tidak perlu memengaruhi sumber daya yang digunakan untuk operasi PUT tersebut

Anda memperbarui personsumber daya yang diidentifikasi sebagai F02E395A235, jadi menggunakan PUT benar. Sekarang sebagai aturan bisnis Anda juga melacak perubahan yang tidak terlihat oleh entitas panggilan (konsumen layanan REST). Ini tidak akan menambahkan item baru di personsumber daya. Cuplikan historis tidak akan dapat diakses menggunakan /person/titik akhir. Jadi saya percaya, PUT harus bisa diterima dalam kasus ini.

Aziz Shaikh
sumber
1
Tidak ada efek samping pada sumber daya yang dimasukkan, tetapi sejumlah efek samping pada hal-hal lain (penghitung, penebangan, jejak audit, ...) sangat dapat diterima.
Marjan Venema