Menghapus sumber daya menggunakan http DELETE

124

Jadi, mengingat kata kerja DELETE di Http idempoten, ketika saya mengeluarkan permintaan berikut, apa yang harus terjadi pada permintaan kedua (atau ketiga, atau keempat, dll ...)?

DELETE /person/123

Pertama kali, sumber daya dihapus dan saya mengembalikan 204 (berhasil, tidak ada konten). Haruskah saya mengembalikan 204 pada panggilan berikutnya atau 404 (tidak ditemukan)?

Craig Wilson
sumber

Jawaban:

153

Karena permintaan HTTP dalam sistem stateless harus independen, hasil dari satu permintaan tidak boleh bergantung pada permintaan sebelumnya. Pertimbangkan apa yang akan terjadi jika dua pengguna melakukan DELETE pada sumber yang sama secara bersamaan. Masuk akal jika permintaan kedua mendapatkan 404. Hal yang sama harus benar jika satu pengguna membuat dua permintaan.

Saya menduga bahwa setelah DELETE mengembalikan dua respons yang berbeda, Anda tidak merasa idempoten. Saya merasa berguna untuk memikirkan permintaan idempoten karena meninggalkan sistem dalam keadaan yang sama, tidak harus memiliki respons yang sama. Jadi, terlepas dari apakah Anda MENGHAPUS sumber daya yang ada, atau mencoba MENGHAPUS sumber daya yang tidak ada, status sumber daya server adalah sama.

Darrel Miller
sumber
4
Terima kasih. Itu sangat masuk akal. Saya memang memikirkan idempoten sebagai mengembalikan respons yang sama.
Craig Wilson
4
@Craig Hati-hati! Di Cookbook, Subbu benar-benar bertentangan dengan apa yang baru saya katakan. Dia mengatakan idempotensi berarti harus mengembalikan respons yang sama. Untungnya, Subbu akan hadir di RESTFest jadi, saya akan menjelaskan dengannya di sana.
Darrel Miller
58
Jika Anda MENGHAPUS sesuatu yang tidak ada, Anda harus mengembalikan 204 (meskipun sumber daya tidak pernah ada). Klien menginginkan sumber daya hilang dan hilang. Mengembalikan 404 mengekspos pemrosesan internal yang tidak penting bagi klien dan akan mengakibatkan kondisi kesalahan yang tidak perlu.
Brian
9
@DarrelMiller Saya kira konsep utama di sini adalah bahwa Anda tidak boleh menggunakan DELETE untuk memeriksa apakah ada sumber daya, Anda akan menggunakan GET terlebih dahulu untuk itu. Kemudian, jika responsnya 200, Anda akan melakukan DELETE; kalau tidak, jangan repot-repot melakukan itu. Jadi saya pikir masuk akal untuk selalu mengembalikan 204 pada DELETE.
manei_cc
10
@ Brian The RFC mengatakan itu seharusnya berperilaku seperti rm. rmmengembalikan kesalahan jika tidak ada. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl
32

Buku masak layanan web RESTful adalah sumber yang bagus untuk ini. Secara kebetulan, pratinjau google-nya menampilkan halaman tentang HAPUS (halaman 11):

Metode DELETE idempoten. Ini menyiratkan bahwa server harus mengembalikan kode respons 200 (OK) bahkan jika server menghapus sumber daya dalam permintaan sebelumnya. Namun dalam praktiknya, menerapkan DELETE sebagai operasi idempoten memerlukan server untuk melacak semua sumber daya yang dihapus. Jika tidak, ini dapat mengembalikan 404 (Tidak Ditemukan).

yves amsellem
sumber
Ya, sepertinya itu sumber daya yang bagus. Namun, bagian HAPUS tidak menarik untuk saya (ini adalah halaman 23 dan pratinjau telah dihapus). Sudahkah kamu membaca buku ini? Apakah Anda kebetulan mengetahui jawaban atas pertanyaan saya?
Craig Wilson
Buku ini harus dimiliki untuk membangun REST (berbicara secara khusus, bukan dalam bahasa).
yves amsellem
7
@Craig Membaca Buku Resep, dikatakan Anda HARUS mengembalikan 200 OK meskipun Anda sudah menghapusnya. Namun, dalam praktiknya yang memerlukan server untuk melacak semua sumber daya yang dihapus, oleh karena itu, Anda BISA menggunakan 404. Selanjutnya dikatakan bahwa masalah keamanan mungkin mengharuskan Anda untuk selalu mengembalikan 404. Page 11.
Darrel Miller
+1 Kedua dan sangat merekomendasikan buku ini untuk merancang layanan RESTful.
Paul DelRe
18
Nah, bukunya salah. Idempotensi tidak menyiratkan bahwa kode status akan sama. Yang relevan adalah status akhir server.
Julian Reschke
13

Saya setuju dengan jawaban yang dipilih saat ini, bahwa DELETE ke-2 (dan ke-3, ke-4, ...) harus mendapatkan 404 . Dan, saya perhatikan bahwa jawaban tersebut mendapat 143 suara positif tetapi juga memiliki komentar sebaliknya yang mendapat 54 suara, jadi komunitas ini dibagi menjadi 2 kubu dengan rasio sekitar 3: 1. Inilah lebih banyak informasi untuk menyelesaikan perdebatan lama ini.

  1. Pertama-tama, JANGAN mulai dengan apa yang "saya" pikirkan, apa yang "Anda" pikirkan, atau apa yang dipikirkan oleh penulis buku lain. Mari kita mulai dengan spesifikasi HTTP yaitu RFC 7231.

    • RFC 7231, bagian 4.3.5 DELETE kebetulan hanya menyebutkan respons yang berhasil seharusnya 2xx, tetapi tidak menyebutkan apa yang akan didapat oleh DELETE berikutnya. Jadi mari kita gali lebih dalam.
    • RFC 7231, bagian 6.5.4 404 Not Found mengatakan tanggapan 404 adalah untuk sumber daya tidak ada. Karena tidak ada metode http tertentu (khususnya, bukan DELETE) yang dipanggil untuk diperlakukan sebaliknya, kami secara intuitif dapat memperoleh kesan (dan memang seharusnya demikian), bahwa permintaan saya DELETE /some/resource/which/does/not/existakan menghasilkan 404. Kemudian,DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/ago mungkin juga mengembalikan 404 Lalu, kenapa harus DELETE /some/resource/i/deleted/five/seconds/agoberbeda? "Tapi bagaimana dengan idempotensi ?!", saya bisa mendengar Anda berteriak seperti itu. Tunggu, kami akan membahasnya.
    • Secara historis, RFC 2616, yang diterbitkan pada tahun 1999, adalah spesifikasi HTTP 1.1 yang paling banyak dirujuk. Sayangnya penjelasannya tentang idempotensi tidak jelas , yang menyisakan ruang untuk semua perdebatan ini. Tapi spesifikasi itu telah digantikan oleh RFC 7231. Dikutip dari RFC 7231, bagian 4.2.2 Metode Idempoten , tekankan saya:

      Metode permintaan dianggap "idempoten" jika EFEK yang diinginkan PADA SERVER beberapa permintaan identik dengan metode itu sama dengan efek untuk satu permintaan tersebut. Dari metode permintaan yang ditentukan oleh spesifikasi ini, PUT, DELETE , dan metode permintaan aman adalah idempoten .

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

  2. Oke jadi ini bukan tentang idempotensi. Tapi kemudian pertanyaan lanjutannya mungkin, bagaimana jika kita masih memilih untuk menggunakan 204 dalam DELETE berikutnya? Apakah ini oke?

    Pertanyaan bagus. Motivasinya dapat dimengerti: untuk memungkinkan klien tetap mencapai hasil yang diinginkan, tanpa mengkhawatirkan penanganan kesalahan. Saya akan mengatakan, mengembalikan 204 dalam DELETE berikutnya, adalah "kebohongan putih" sisi server yang sebagian besar tidak berbahaya, yang sisi klien tidak akan segera membedakannya. Itulah mengapa ada ~ 25% orang melakukan itu di alam liar dan tampaknya masih berhasil. Ingatlah bahwa, kebohongan semacam itu dapat dianggap aneh secara semantik, karena GET /non-existmengembalikan 404 tetapi DELETE /non-existmemberikan 204, pada saat itu klien akan mengetahui bahwa layanan Anda tidak sepenuhnya sesuai dengan bagian 6.5.4 404 Not Found .

    Namun saya ingin menunjukkan bahwa, cara yang dimaksudkan yang ditunjukkan oleh RFC 7231, yaitu mengembalikan 404 pada DELETE berikutnya, seharusnya tidak menjadi masalah sejak awal. 3x lebih banyak pengembang memilih untuk melakukan itu, dan apakah Anda pernah mendengar insiden besar atau keluhan yang disebabkan oleh klien yang tidak dapat menangani 404? Agaknya, tidak, dan itu karena, klien yang layak yang mengimplementasikan HTTP DELETE (atau metode HTTP apa pun, dalam hal ini), tidak akan secara membabi buta berasumsi bahwa hasilnya akan selalu berhasil 2xx. Dan kemudian, setelah pengembang mulai mempertimbangkan penanganan kesalahan, 404 Not Found akan menjadi salah satu kesalahan pertama yang terlintas dalam pikiran. Pada titik itu, dia mungkin akan menarik kesimpulan bahwa, secara semantik aman untuk operasi HTTP DELETE mengabaikan kesalahan 404. Dan mereka melakukannya.

Masalah terpecahkan.

RayLuo
sumber
2
+1 "idempotensi adalah tentang efek pada server". Menjawab dengan cermat. Sudah selesai dilakukan dengan baik! Saya percaya 404 untuk permintaan DELETE berikutnya.
nwayve
11

HAPUS Pertama : 200 atau 204.

HAPUS berikutnya : 200 atau 204.

Rasional : DELETE harus idempoten. Jika Anda mengembalikan 404 pada HAPUS kedua, tanggapan Anda berubah dari kode sukses menjadi kode kesalahan . Program klien mungkin mengambil tindakan yang salah berdasarkan asumsi DELETE gagal.

Contoh :

  • Misalkan operasi DELETE Anda adalah bagian dari operasi multi-langkah (atau "saga") yang dijalankan oleh program klien.
  • Program klien dapat berupa aplikasi seluler yang melakukan transaksi bank, misalnya.
  • Misalkan program klien memiliki percobaan ulang otomatis untuk operasi DELETE (masuk akal, karena DELETE seharusnya idempoten).
  • Katakanlah DELETE pertama berhasil dijalankan, tetapi 200 respons hilang dalam perjalanannya ke program klien.
  • Program klien akan mencoba kembali HAPUS.
  • Jika upaya kedua mengembalikan 404, program klien dapat membatalkan operasi keseluruhan karena kode kesalahan ini.
  • Tetapi karena DELETE pertama berhasil dijalankan di server, sistem mungkin dibiarkan pada keadaan yang tidak konsisten .
  • Jika usaha kedua mengembalikan 200 atau 204, program klien akan berjalan seperti yang diharapkan.

Hanya untuk mengilustrasikan penggunaan pendekatan ini, panduan gaya API HTTP untuk PayPal memiliki panduan berikut:

HAPUS: Metode ini HARUS mengembalikan kode status 204 karena tidak perlu mengembalikan konten apa pun dalam banyak kasus karena permintaannya adalah untuk menghapus sumber daya dan itu berhasil dihapus.

Karena metode DELETE HARUS juga idempoten, metode HARUS tetap menampilkan 204, meskipun sumber daya sudah dihapus. Biasanya konsumen API tidak peduli jika sumber daya telah dihapus sebagai bagian dari operasi ini, atau sebelumnya. Ini juga alasan mengapa 204, bukan 404, harus dikembalikan.

Paulo Merson
sumber
1
Pertanyaannya adalah, apa yang penting bagi klien, apakah itu menghapus sumber daya, atau bahwa sumber daya telah dihapus. Bagaimana jika beberapa klien lain menghapus sumber daya selama saga. Apakah Anda benar-benar ingin gagal mengingat tujuan klien telah tercapai?
Darrel Miller
1
@DarrelPoin yang bagus. Yang lebih penting tergantung pada konteks bisnis. Namun secara umum, saya lebih suka mengembalikan 204 pada upaya HAPUS kedua, bahkan jika sumber daya telah dihapus oleh klien lain. Saya tidak ingin layanan gagal (yaitu, 404) mengingat tujuan klien tercapai.
Paulo Merson
2
Seperti yang disebutkan orang lain, idempotensi bukanlah kode respons Anda, melainkan status server Anda.
Niranjan
@Niranjan Saya setuju idempotensi adalah tentang status server, tetapi kode respons yang berbeda dapat mendorong klien untuk mengubah status server secara tidak perlu dengan membatalkan saga yang sedang berlangsung.
Paulo Merson
@Paulo Merson kode apa yang akan Anda kembalikan jika klien meminta penghapusan item yang TIDAK PERNAH ada? 204? atau 404? Jika Anda selalu mengembalikan 204 apa gunanya memeriksa kode pengembalian?
frenchone