ISTIRAHAT, HAPUS HTTP dan parameter

135

Apakah ada sesuatu yang non-TENANG tentang memberikan parameter ke permintaan HTTP DELETE?


Skenario saya adalah saya memodelkan "Anda yakin ingin menghapusnya?" skenario. Dalam beberapa kasus, keadaan sumber daya menunjukkan bahwa penghapusan yang diminta mungkin tidak valid. Anda mungkin dapat membayangkan sendiri beberapa skenario di mana konfirmasi penghapusan diperlukan

Solusi yang kami adopsi adalah meneruskan parameter ke permintaan hapus untuk menunjukkan bahwa tidak apa-apa untuk melanjutkan penghapusan ("? Force_delete = true")

misalnya

DELETE http://server/resource/id?force_delete=true

Saya percaya bahwa itu masih tenang sejak:

(a) Semantik DELETE tidak sedang diubah - pengguna masih dapat mengirim permintaan DELETE normal tetapi ini mungkin gagal dengan 409 dan badan tanggapan akan menjelaskan alasannya. Saya katakan mungkin gagal karena (karena alasan tidak layak dijelaskan) pada beberapa kesempatan tidak ada alasan untuk meminta pengguna.

(B) Tidak ada dalam disertasi Roy untuk menyarankan bahwa itu bertentangan dengan semangat REST - mengapa akan ada karena HTTP hanya satu implementasi dari REST jadi mengapa melewati parameter HTTP penting


Dapatkah seseorang mengarahkan saya pada pernyataan definitif yang mendukung alasan mengapa ini tidak tenang?

Pada pertanyaan terkait, jika pengguna tidak menentukan force_delete maka saya kembali 409 Conflict- apakah itu kode respons yang paling tepat?


Mengikuti

Setelah beberapa penelitian lebih lanjut, saya berpikir bahwa menambahkan parameter ke DELETE dapat melanggar beberapa prinsip.

Yang pertama adalah bahwa implementasi mungkin melanggar "Uniform Interface" (lihat bagian 5.1.5 disertasi Roy

Dengan menambahkan 'force_delete' kami menambahkan kendala tambahan ke metode DELETE yang sudah didefinisikan dengan baik. Batasan ini hanya berarti bagi kita.

Anda juga bisa berpendapat bahwa itu melanggar "5.1.2 Client-Server" karena dialog konfirmasi benar-benar menjadi perhatian UI dan sekali lagi tidak semua klien ingin mengonfirmasi penghapusan.

Saran siapa pun?

Chris McCauley
sumber
1
Url Anda untuk disertasi Roy berisi ")" yang menyebabkan 404. ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm berfungsi.
NuclearPeon

Jawaban:

78

Tidak, itu tidak tenang. Satu-satunya alasan mengapa Anda harus meletakkan kata kerja ( force_delete) ke dalam URI adalah jika Anda perlu membebani metode GET / POST di lingkungan di mana metode PUT / DELETE tidak tersedia. Menilai dari penggunaan Anda terhadap metode DELETE, ini bukan masalahnya.

Kode kesalahan HTTP 409/Conflict harus digunakan untuk situasi di mana ada konflik yang mencegah layanan RESTful untuk melakukan operasi, tetapi masih ada kemungkinan bahwa pengguna mungkin dapat menyelesaikan konflik itu sendiri. Konfirmasi pra-penghapusan (di mana tidak ada konflik nyata yang akan mencegah penghapusan) bukanlah konflik semata, karena tidak ada yang menghalangi API untuk melakukan operasi yang diminta.

Seperti yang dikatakan Alex (saya tidak tahu siapa yang menurunkannya, dia benar), ini harus ditangani di UI, karena layanan RESTful hanya memproses permintaan dan karena itu harus stateless (yaitu tidak boleh bergantung pada konfirmasi dengan memegang informasi sisi server tentang permintaan).

Dua contoh cara melakukan ini di UI adalah:

  • pra-HTML5 : * tampilkan dialog konfirmasi JS ke pengguna, dan kirim permintaan hanya jika pengguna mengonfirmasi
  • HTML5 : * gunakan formulir dengan aksi DELETE di mana formulir hanya berisi tombol "Konfirmasi" dan "Batalkan" ("Konfirmasi" akan menjadi tombol kirim)

(*) Harap perhatikan bahwa versi HTML sebelum 5 tidak mendukung metode PUT dan HAPUS secara native, namun sebagian besar browser modern dapat melakukan kedua metode ini melalui panggilan AJAX. Lihat utas ini untuk detail tentang dukungan lintas-browser.


Memperbarui (berdasarkan investigasi dan diskusi tambahan):

Skenario di mana layanan akan memerlukan force_delete=truebendera untuk hadir melanggar antarmuka seragam seperti yang didefinisikan dalam disertasi Roy Fielding. Juga, sesuai HTTP RFC , metode DELETE dapat ditimpa pada server asal (klien), menyiratkan bahwa ini tidak dilakukan pada server target (layanan).

Jadi, begitu layanan menerima permintaan DELETE, ia harus memprosesnya tanpa memerlukan konfirmasi tambahan (terlepas apakah layanan tersebut benar-benar melakukan operasi).

MicE
sumber
2
Bisakah Anda menjelaskan kendala REST mana yang dilanggar? Mempertimbangkan bahwa URI harus buram untuk klien, mengapa Anda percaya bahwa harapan klien tidak terpenuhi dengan penggunaan HTTP DELETE yang menghapus satu sumber tetapi gagal menghapus yang lain. Saya tidak yakin 409 adalah kode status terbaik untuk dikembalikan tetapi selain sedikit implementasi yang aneh, saya tidak dapat menemukan kendala REST yang sedang rusak.
Darrel Miller
2
@ Darrel: (imho) itu melanggar antarmuka seragam dengan metode DELETE tidak berkinerja sesuai standar HTTP. Pertimbangkan klien REST yang mengasumsikan layanan REST standar - bagaimana layanan akan memberi tahu klien bahwa ia perlu menambahkan force_delete=true? Sesuai HTTP RFC, metode DELETE dapat ditimpa pada server asal (klien), menyiratkan bahwa ini tidak dilakukan pada server target (layanan). Jadi pemahaman saya adalah bahwa begitu layanan menerima permintaan DELETE, harus memprosesnya tanpa memerlukan konfirmasi (terlepas apakah layanan tersebut benar-benar melakukan operasi).
MicE
1
@ Chris, ke poin kedua Anda: ya, itu adalah pemahaman saya juga, yaitu bahwa negara menunjukkan konflik nyata dan bukan kebutuhan untuk konfirmasi. Saya baru saja melihat pembaruan yang Anda lakukan dalam pertanyaan Anda, dan saya setuju - ketika saya sedang mencari sendiri, saya sampai pada kesimpulan yang sama (bahwa ini melanggar antarmuka seragam, dan bahwa konfirmasi harus dilakukan pada klien / UI sisi). Saya juga menemukan utas yang sangat menarik di sini, mungkin membantu: mail-archive.com/[email protected]/msg13578.html
MicE
2
@ Mice Untuk sebagian besar saya setuju dengan Anda bahwa itu bukan cara yang ideal untuk menangani skenario ini. Saya hanya sedikit pilih-pilih tentang label "itu tidak tenang". Untuk sementara di sini frasa itu dilemparkan pada segalanya. Namun, akan mungkin untuk menetapkan aturan untuk jenis media yang mengatakan jika Anda mencoba untuk HAPUS sumber daya dan Anda mendapatkan kesalahan (saya akan mengatakan 403 dilarang akan lebih baik dari 409), maka klien harus mencoba HAPUS pada sumber daya terkait dengan menempelkan "force_delete = true". Di satu sisi itu agak seperti otorisasi. Lakukan GET, dapatkan 401, tambahkan tajuk auth dan GET lagi.
Darrel Miller
2
@ Darrel: itu poin yang sangat bagus, terima kasih. Dan saya telah melihat orang-orang melemparkan label yang tidak tenang untuk diri saya sendiri. Ini mungkin menjadi kasus bahwa saat ini penghalang antara layanan dan aplikasi web menjadi sangat berkabut, sehingga satu set orang dapat melihat ini dari sudut pandang layanan murni, sementara yang lain melihatnya dari sudut pandang aplikasi / layanan campuran. Itu saya percaya di mana pertanyaan sebenarnya tentang bagaimana melakukan konfirmasi mulai berlaku. @ Chris: diperbarui - terima kasih Pak untuk topik dan diskusi yang sangat menarik!
MicE
35

Saya pikir ini tidak tenang. Saya tidak berpikir layanan yang tenang harus menangani persyaratan memaksa pengguna untuk mengonfirmasi penghapusan. Saya akan menangani ini di UI.

Apakah menentukan force_delete = true masuk akal jika ini adalah API program? Jika seseorang menulis skrip untuk menghapus sumber ini, apakah Anda ingin memaksa mereka untuk menentukan force_delete = true untuk benar-benar menghapus sumber daya?

Alex Rockwell
sumber
Paragraf pertama dari tanggapan Anda adalah pendapat Anda dan saya menghargai itu, tetapi Anda belum menunjuk sesuatu dalam literatur yang melarang penggunaan URI seperti ini - itu masih mengidentifikasi sumber daya dan kata kerja HTTP yang paling tepat sedang digunakan. Sebagai jawaban atas pertanyaan Anda; ya itu masih masuk akal (menurut saya). Saya akan mengharapkan skrip (mungkin berdasarkan CURL) untuk menghormati tanggapan 409 dan menyarankan kepada pengguna bagaimana permintaan dapat dikirim ulang - semua berdasarkan pada badan tanggapan saya
Chris McCauley
Poin bagus tentang membandingkan API web dengan API program. Itu sering kali merupakan cara yang baik untuk mengetahui apakah suatu API tenang atau tidak.
laurent
18

Ini pertanyaan lama, tapi di sini ada beberapa komentar ...

  1. Dalam SQL, perintah DELETE menerima parameter "CASCADE", yang memungkinkan Anda menentukan bahwa objek dependen juga harus dihapus. Ini adalah contoh parameter DELETE yang masuk akal, tetapi 'man rm' dapat memberikan yang lain. Bagaimana kasus-kasus ini dapat diimplementasikan dalam REST / HTTP tanpa parameter?
  2. @ Jan, tampaknya menjadi konvensi yang mapan bahwa bagian jalur URL mengidentifikasi sumber daya, sedangkan querystring tidak (setidaknya tidak harus). Banyak contoh: mendapatkan sumber daya yang sama tetapi dalam format yang berbeda, mendapatkan bidang sumber daya tertentu, dll. Jika kita menganggap querystring sebagai bagian dari pengidentifikasi sumber daya, tidak mungkin untuk memiliki konsep "pandangan berbeda dari sumber daya yang sama" tanpa beralih ke mekanisme non-TENANG seperti negosiasi konten HTTP (yang dapat tidak diinginkan karena berbagai alasan).
Shay Rojansky
sumber
Terima kasih telah menambahkan ini ke percakapan, meskipun itu bukan percakapan sejak bertahun-tahun.
silviot
6

Selain jawaban Alex:

Perhatikan bahwa http: // server / resource / id? Force_delete = true mengidentifikasi sumber yang berbeda dari http: // server / resource / id . Misalnya, ada perbedaan besar apakah Anda menghapus / customers /? Status = lama atau / pelanggan /.

Jan

Jan Algermissen
sumber
Saya tidak setuju, saya bebas memberikan beberapa URI untuk mengidentifikasi sumber daya yang sama.
Chris McCauley
18
Yap - semua orang bebas membuat kekacauan :-)
Jan Algermissen
Indikasi URI kanonik dapat membantu dengan ini: googlewebmastercentral.blogspot.com/2009/02/…
MicE
@ Chris Hanya harus ada satu URI yang mengembalikan representasi sumber daya. URI lain dapat merujuk ke konsep yang sama tetapi melakukan GET harus mengembalikan 303 Lihat Lainnya. Dan hanya untuk melawan keberatan yang jelas terhadap hal ini, /foo.xml dan /foo.json adalah dua sumber yang berbeda.
Darrel Miller
@Darrell - setuju tetapi formatnya tidak menjadi masalah di sini. Juga .format adalah konvensi dalam Rails dan kerangka kerja lain yang bukan merupakan bagian dari REST - Anda harus menggunakan negosiasi konten dalam HTTP dengan MIME atau Microformats untuk sepenuhnya mengimplementasikannya.
Chris McCauley