Apakah REST DELETE benar-benar idempoten?

166

DELETE seharusnya idempoten.

Jika saya HAPUS http://example.com/account/123 itu akan menghapus akun.

Jika saya melakukannya lagi, apakah saya mengharapkan 404, karena akun tidak ada lagi? Bagaimana jika saya mencoba HAPUS akun yang belum pernah ada?

Ben Noland
sumber
11
Selain jawaban, saya sarankan untuk tidak terlalu fokus pada karakteristik idempoten secara umum: itu tidak mengatakan apa-apa tentang komutatifitas dan permintaan bersamaan. Misalnya N +1 dari permintaan PUT "R1" yang sama harus memiliki efek yang sama, tetapi Anda tidak tahu apakah klien lain membuat permintaan PUT / DELETE "R2" yang berbeda di antara Anda, jadi ketika n R1 = R1 dan m R2 = R2, sesuatu di mana Anda mendapatkan permintaan "R1" dan "R2" tidak akan selalu "terlihat" idempoten jika Anda hanya mengambil perspektif satu klien.
Bruno

Jawaban:

188

Idempotensi mengacu pada keadaan sistem setelah permintaan selesai


Dalam semua kasus (terlepas dari masalah kesalahan - lihat di bawah), akun tidak ada lagi.

Dari sini

"Metode juga dapat memiliki properti" idempotensi "dalam hal itu ( selain dari kesalahan atau masalah kedaluwarsa ) efek samping dari N> 0 permintaan yang identik adalah sama dengan untuk satu permintaan. Metode yang DAPATKAN, HEAD, PUT dan DELETE berbagi properti ini. Juga, metode OPSI dan LALU TIDAK HARUS memiliki efek samping, dan karenanya inheren idempoten. "


Bit kunci ada efek samping dari N> 0 permintaan identik adalah sama seperti untuk satu permintaan.

Anda akan benar untuk mengharapkan bahwa kode status akan berbeda tetapi ini tidak mempengaruhi konsep inti idempotensi - Anda dapat mengirim permintaan lebih dari sekali tanpa perubahan tambahan ke keadaan server.

Chris McCauley
sumber
3
Efek samping! == keadaan server
wprl
2
@ wprl Ada perdebatan tentang apa sebenarnya "efek samping" ini. Ini mungkin "keadaan server" atau mungkin respons dikirim ke klien. leedavis81.github.io/is-a-http-delete-requests-idempotent
Alireza
Berikut adalah argumen bahwa 404 pada DELETE kedua dapat benar-benar mengubah keadaan server: stackoverflow.com/a/45194747/317522
Paulo Merson
1
@ PauloMerson Terima kasih, secara pribadi saya tidak berpikir itu penting apakah pengembalian kedua adalah 404 atau 200, keadaan server tidak berubah jadi saya senang dengan itu.
Chris McCauley
46

Idempoten adalah tentang efek permintaan, bukan tentang kode respons yang Anda dapatkan.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 mengatakan:

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.

Meskipun Anda mungkin mendapatkan kode respons yang berbeda, efek pengiriman permintaan N + 1 DELETE ke sumber daya yang sama dapat dianggap sama.

Bruno
sumber
13

Perbedaan penting adalah bahwa idempoten mengacu pada efek samping , tidak semua efek atau respons. Jika Anda melakukannya DELETE http://example.com/account/123maka efeknya adalah akun 123 sekarang dihapus dari server. Itulah satu-satunya efek, satu-satunya perubahan pada status server. Sekarang katakanlah Anda melakukan DELETE http://example.com/account/123permintaan yang sama lagi, server akan merespons secara berbeda, tetapi kondisinya sama.

Ini tidak seperti permintaan DELETE memutuskan untuk mengubah keadaan server dengan cara yang berbeda karena akun itu hilang, seperti menghapus akun lain, atau meninggalkan log kesalahan. Tidak, Anda dapat memanggil permintaan DELETE yang sama jutaan kali dan Anda dapat yakin bahwa server berada dalam kondisi yang sama dengan yang pertama kali Anda menyebutnya .

Janac Meena
sumber
7

Dari HTTP RFC :

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.

Perhatikan itu "efek samping", bukan "respons".

fumanchu
sumber
7

Iya. Terlepas dari kode respons.

Dari RFC terbaru untuk HTTP 1.1 (penekanan milik saya):

Metode idempoten dibedakan karena permintaan dapat diulang secara otomatis jika terjadi kegagalan komunikasi sebelum klien dapat membaca respons server. Misalnya, jika klien mengirim permintaan PUT dan koneksi yang mendasarinya ditutup sebelum respons apa pun diterima, maka klien dapat membuat koneksi baru dan mencoba kembali permintaan idempoten. Ia tahu bahwa mengulangi permintaan akan memiliki efek yang dimaksudkan sama, bahkan jika permintaan asli berhasil, meskipun responsnya mungkin berbeda.

Secara eksplisit dikatakan bahwa responsnya mungkin berbeda. Lebih penting lagi, itu menunjukkan alasan konsep: jika suatu tindakan idempoten, klien dapat mengulangi tindakan ketika menemukan kesalahan, dan tahu bahwa itu tidak akan menabrak apa pun dengan melakukannya; jika tidak, klien harus membuat permintaan tambahan (mungkin GET) untuk melihat apakah yang sebelumnya efektif, sebelum mengulangi tindakan dengan aman. Selama server dapat memberikan jaminan seperti itu, tindakannya idempoten. Kutipan dari komentar lain :

Komputasi idempotensi adalah tentang kekuatan suatu sistem. Karena hal-hal dapat gagal (mis. Pemadaman jaringan), ketika kegagalan terdeteksi, bagaimana Anda memulihkan? Pemulihan termudah adalah hanya melakukannya lagi, tetapi itu hanya berfungsi jika melakukannya lagi idempoten. Misalnya discard(x)idempoten, tetapi pop()tidak. Ini semua tentang pemulihan kesalahan.

Franklin Yu
sumber
2

Saya pikir hal yang sama, 404 - Akun tidak ada.

Anda bisa membantah 400 - Permintaan Buruk. Tetapi dalam arti REST, objek yang Anda minta untuk melakukan tindakan tidak ada. Itu berarti 404.

Jason McCreary
sumber
1
Untuk menghasilkan 400, Anda harus tahu bahwa objek itu dulu ada, yang sangat tidak tenang.
annakata
1
@annakata, 400 bahkan bukan untuk sumber daya yang dulu ada (mungkin Anda memiliki 410 / Gone dalam pikiran), itu untuk permintaan buruk "Permintaan tidak dapat dipahami oleh server karena sintaksis cacat."
Bruno
3
@ Bruno - Saya sadar apa artinya, OP mengutipnya.
annakata
1
Saya pikir 200 akan baik-baik saja. Anda ingin keadaan server bahwa akun hilang. Apakah penting permintaan mana yang membuatnya pergi? Itu masih pergi pada permintaan kedua, keadaan server tidak berubah.
Andy
2

Dikutip dari jawaban saya yang lain di sini :

Secara historis, RFC 2616, diterbitkan pada tahun 1999, adalah spesifikasi HTTP 1.1 yang paling banyak dirujuk. Sayangnya deskripsi tentang idempotensi tidak jelas , sehingga menyisakan ruang untuk semua perdebatan ini. Tetapi spesifikasi itu telah digantikan oleh RFC 7231. Dikutip dari RFC 7231, bagian 4.2.2 Metode Idempoten , penekanan pada tambang:

Suatu metode permintaan dianggap "idempoten" jika DAMPAK yang dimaksudkan pada SERVER dari beberapa permintaan identik dengan metode itu sama dengan efek untuk satu permintaan semacam itu. Dari metode permintaan yang ditentukan oleh spesifikasi ini, PUT, DELETE , dan metode permintaan aman idempoten .

Jadi, ada tertulis dalam spesifikasi, idempotensi adalah semua tentang efek pada server. DELETE pertama mengembalikan 204 dan kemudian DELETE mengembalikan 404, kode status berbeda seperti itu TIDAK membuat DELETE non-idempoten. Menggunakan argumen ini untuk membenarkan pengembalian 204 berikutnya, sama sekali tidak relevan.


OK jadi ini bukan tentang idempotensi. Tetapi kemudian pertanyaan lanjutannya adalah, bagaimana jika kita masih memilih untuk menggunakan 204 dalam DELETE berikutnya? Apakah itu oke?

Pertanyaan bagus. Motivasinya dapat dimengerti: untuk memungkinkan klien untuk tetap mencapai hasil yang diinginkan, tanpa khawatir tentang penanganan kesalahan. Saya akan mengatakan, mengembalikan 204 di DELETE berikutnya, adalah "kebohongan putih" di sisi server yang sebagian besar tidak berbahaya, yang pihak klien tidak akan segera memberi tahu perbedaannya. Itu sebabnya ada orang yang melakukan itu di alam liar dan masih berfungsi. Hanya perlu diingat bahwa, kebohongan seperti itu dapat dianggap aneh secara semantik, karena "DAPATKAN / tidak ada" mengembalikan 404 tetapi "HAPUS / tidak ada" memberi 204, pada saat itu klien akan mengetahui layanan Anda tidak sepenuhnya mematuhi bagian 6.5.4 404 Tidak Ditemukan .

Tapi kemudian, cara yang dimaksud mengisyaratkan oleh RFC 7231, yaitu mengembalikan 404 pada DELETE berikutnya, seharusnya tidak menjadi masalah. Banyak lagi pengembang yang memilih untuk melakukan itu. Mungkin karena, setiap klien yang mengimplementasikan HTTP DELETE (atau metode HTTP apa pun), tidak akan secara membabi buta menganggap bahwa hasilnya akan selalu berhasil 2xx. Dan kemudian, setelah pengembang mulai mempertimbangkan penanganan kesalahan, 404 Not Found akan menjadi salah satu kesalahan pertama yang muncul di pikiran. Pada titik itu, ia diharapkan akan menarik kesimpulan bahwa, semantik aman untuk operasi HTTP DELETE untuk mengabaikan kesalahan 404. Masalah terpecahkan.

RayLuo
sumber