Mengapa metode PATCH tidak idempoten?

48

Saya bertanya-tanya tentang ini.

Misalkan saya memiliki usersumber daya iddan namebidang. Jika saya ingin memperbarui bidang, saya bisa melakukan permintaan PATCH ke sumber daya seperti ini

PATCH /users/42
{"name": "john doe"} 

Dan kemudian aplikasi akan memperbarui nama pengguna 42.

Tetapi mengapa jika saya mengulangi permintaan ini hasilnya akan berbeda?

Menurut RFC 5789

PATCH tidak aman atau idempoten

mattecapu
sumber
bagaimana jika antara pemanggilan orang lain melakukan permintaan untuk memperbarui pengguna 42{"name": "bendjamin franklin"}
agung
@gnat tidakkah argumen serupa juga berlaku untuk metode PUT yang dianggap idempoten? (lihat goo.gl/t24ZSJ )
mattecapu
"PUT memiliki semantik idempoten dan dengan demikian dapat digunakan dengan aman untuk pembaruan absolut (yaitu kami mengirim seluruh status sumber daya ke server), tetapi tidak juga untuk pembaruan relatif (yaitu kami mengirim hanya perubahan ke status sumber daya) , karena itu akan melanggar semantiknya ... "( permintaan POST dan PUT - apakah hanya konvensi? )
agas
1
Jelas ... Tapi Anda bisa mengatakan PUT tidak idempoten karena antara dua permintaan yang sama klien kedua dapat membuat permintaan ketiga di antara keduanya. Tapi karena kami tidak peduli dengan data sebelumnya, itu tidak masalah. Argumen yang sama berlaku untuk permintaan PATCH.
mattecapu
2
Saya mengambil kebebasan untuk menambahkan referensi ke spesifikasi yang relevan, karena saya percaya itu sangat relevan dalam konteks pertanyaan ini.
Pete

Jawaban:

34

Permintaan PATCH bisa saja idempoten, tetapi tidak harus begitu. Itulah alasan mengapa ini dicirikan sebagai non-idempoten.

Apakah PATCH dapat menjadi idempoten atau tidak sangat bergantung pada bagaimana perubahan yang diperlukan dikomunikasikan.
Misalnya, jika format tambalan dalam bentuk {change: 'Name' from: 'benjamin franklin' to: 'john doe'}, maka setiap permintaan PATCH setelah yang pertama akan memiliki efek yang berbeda (respons kegagalan) dari permintaan pertama.
Alasan lain untuk non-idempotensi adalah penerapan modifikasi pada hal lain selain sumber daya asli dapat menjadikan sumber daya tidak valid. Ini juga akan menjadi masalah jika Anda menerapkan perubahan beberapa kali.

Bart van Ingen Schenau
sumber
3
Saya tidak mengerti paragraf terakhir, dapatkah Anda memberikan contoh bagaimana "menerapkan modifikasi pada hal lain selain sumber daya asli dapat membuat sumber daya tidak valid", dan bagaimana ini berkaitan dengan menerapkan perubahan beberapa kali ke sumber daya yang sama?
Robin Green
3
@RobinGreen: Asumsikan bahwa sumber daya diwakili dalam XML dengan persyaratan paling banyak ada satu <name>elemen. Jika PATCH menambahkan <name>elemen ke sumber daya yang awalnya tidak mengandung satu, maka menerapkan PATCH dua kali (atau menerapkannya ke sumber daya yang sudah mengandung a <name>) membuat sumber daya tidak valid, karena tiba-tiba akan berisi dua <name>elemen yang tidak diperbolehkan untuk sumber daya semacam itu.
Bart van Ingen Schenau
13
Contoh pertama yang Anda berikan adalah IMHO yang tidak relevan karena idempoten. Contoh dengan DELETE yang idempoten, permintaan pertama: sumber daya ada tetapi telah dihapus (mengembalikan 2xx), permintaan kedua: sumber daya tidak ada dan masih tidak ada setelah permintaan, mengembalikan 4xx. Status server tidak berubah, sehingga idempotensi. Dalam contoh Anda, permintaan pertama: PATCH dari BenFra ke JohDoe, nama sumber daya adalah BenFra tetapi sekarang adalah JohDoe (mengembalikan 2xx), permintaan kedua: PATCH dari BenFra ke JohDoe, nama sumber daya adalah JohDoe dan masih adalah JohDoe (pengembalian 4xx). Jadi ini tidak menunjukkan PATCH bisa menjadi non-leluhur.
sp00m
Lebih detail di sini: stackoverflow.com/q/4088350/1225328
sp00m
8

Saya pikir jawaban yang jelas ketika PATCH dalam tidak idempoten adalah paragraf ini dari RFC 5789:

Ada juga kasus di mana format tambalan tidak perlu beroperasi dari titik dasar yang diketahui (misalnya, menambahkan baris teks ke file log, atau baris yang tidak bertabrakan ke tabel database), dalam hal ini tidak diperlukan perawatan yang sama dalam permintaan klien. .

Karena RFC menentukan bahwa tambalan berisi beberapa "perubahan umum" pada sumber daya, kita harus melihat lebih dari sekadar penggantian bidang biasa. Jika sumber daya untuk penghitung, maka tambalan dapat meminta peningkatannya, yang jelas bukan idempotet.

Ivan
sumber
2

PATCHpermintaan menguraikan serangkaian operasi untuk diterapkan pada sumber daya, jika Anda menerapkan rangkaian operasi yang sama dua kali pada sumber daya yang sama, hasilnya mungkin tidak sama. Ini karena mendefinisikan operasi terserah Anda. Dengan kata lain Anda harus mendefinisikan aturan penggabungan .

Ingatlah bahwa PATCHpermintaan dapat digunakan untuk menambal sumber daya dalam berbagai format, bukan hanya JSON.

Jadi PATCHpermintaan bisa menjadi idempoten jika Anda mendefinisikan aturan penggabungan menjadi idempoten .

Contoh idempoten:

// Original resource
{
  name: 'Tito',
  age: 32
}

// PATCH request
{
  age: 33
}

// New resource
{
  name: 'Tito',
  age: 33
}

Contoh non-idempoten:

// Original resource
{
  name: 'Tito',
  age: 32
}

// PATCH request
{
  $increment: 'age'
}

// New resource
{
  name: 'Tito',
  age: 33
}

Dalam contoh kedua saya menggunakan sintaksis "Mongo like" yang saya buat untuk menambah atribut. Jelas ini bukan idempoten, karena mengirimkan permintaan yang sama beberapa kali akan menghasilkan hasil yang berbeda setiap kali.

Sekarang Anda mungkin bertanya-tanya apakah menggunakan sintaks yang dibuat seperti itu valid. Menurut standar , itu adalah:

Perbedaan antara permintaan PUT dan PATCH tercermin dalam cara server memproses entitas terlampir untuk memodifikasi sumber daya yang diidentifikasi oleh Request-URI. Dalam permintaan PUT, entitas terlampir dianggap sebagai versi modifikasi dari sumber daya yang disimpan di server asal, dan klien meminta agar versi yang disimpan diganti. Dengan PATCH, bagaimanapun, entitas terlampir berisi serangkaian instruksi yang menggambarkan bagaimana sumber daya yang saat ini berada di server asal harus dimodifikasi untuk menghasilkan versi baru.

Dan Anda mungkin juga bertanya-tanya apakah itu tenang untuk menggunakan PATCHpermintaan dengan cara ini, dan banyak orang menganggapnya tidak, inilah jawaban yang baik dengan banyak komentar tentang masalah ini.

Jbm
sumber