Pertanyaan PUT vs. POST di REST


Menurut Spec HTTP / 1.1:

Itu POST metode digunakan untuk meminta server asal menerima entitas terlampir dalam permintaan sebagai bawahan baru dari sumber yang diidentifikasi oleh Request-URI dalam Request-Line

Dengan kata lain, POST digunakan untuk membuat.

Itu PUT meminta metode agar entitas tertutup disimpan di bawah yang disediakan Request-URI. Jika itu Request-URI mengacu pada sumber daya yang sudah ada, entitas tertutup HARUS dianggap sebagai versi modifikasi dari yang berada di server asal. Jika itu Request-URI tidak menunjuk ke sumber daya yang ada, dan bahwa URI mampu didefinisikan sebagai sumber daya baru oleh agen pengguna yang meminta, server asal dapat membuat sumber daya dengan URI itu. "

Itu adalah, PUT digunakan untuk buat atau perbarui.

Jadi, mana yang harus digunakan untuk membuat sumber daya? Atau seseorang perlu mendukung keduanya?


4456
2018-03-10 14:25


asal


Jawaban:


Secara keseluruhan: 

Baik PUT dan POST dapat digunakan untuk membuat.

Anda harus bertanya "untuk apa Anda melakukan aksi itu?" untuk membedakan apa yang seharusnya Anda gunakan. Mari asumsikan Anda sedang merancang API untuk mengajukan pertanyaan. Jika Anda ingin menggunakan POST maka Anda akan melakukannya ke daftar pertanyaan. Jika Anda ingin menggunakan PUT, maka Anda akan melakukannya untuk pertanyaan tertentu.

Hebat keduanya bisa digunakan, jadi mana yang harus saya gunakan dalam desain RESTful saya:

Anda tidak perlu mendukung PUT dan POST.

Yang digunakan adalah yang tersisa untuk Anda. Tapi ingatlah untuk menggunakan yang benar tergantung pada objek apa yang Anda rujuk dalam permintaan.

Beberapa pertimbangan:

  • Apakah Anda menyebutkan objek URL yang Anda buat secara eksplisit, atau membiarkan server memutuskan? Jika Anda beri nama, gunakan PUT. Jika Anda membiarkan server memutuskan, maka gunakan POST.
  • PUT adalah idempoten, jadi jika Anda PUT objek dua kali, itu tidak berpengaruh. Ini adalah properti yang bagus, jadi saya akan menggunakan PUT jika memungkinkan.
  • Anda dapat memperbarui atau membuat sumber daya dengan PUT dengan URL objek yang sama
  • Dengan POST, Anda dapat meminta 2 permintaan sekaligus membuat modifikasi pada URL, dan mereka dapat memperbarui bagian-bagian berbeda dari objek.

Sebuah contoh:

Saya menulis yang berikut sebagai bagian dari jawaban lain tentang SO mengenai hal ini:

POS:

Digunakan untuk memodifikasi dan memperbarui sumber daya

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

Perhatikan bahwa berikut ini adalah kesalahan:

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

Jika URL belum dibuat, Anda   tidak boleh menggunakan POST untuk membuatnya   saat menentukan nama. Ini seharusnya   menghasilkan kesalahan 'sumber daya tidak ditemukan'   karena <new_question> tidak ada   namun. Anda harus PUT the <new_question>   sumber daya di server terlebih dahulu.

Anda bahkan bisa melakukan sesuatu seperti itu   ini untuk membuat sumber daya menggunakan POST:

POST /questions HTTP/1.1
Host: www.example.com/

Perhatikan bahwa dalam hal ini sumber daya   nama tidak ditentukan, objek baru   Jalur URL akan dikembalikan kepada Anda.

TARUH: 

Digunakan untuk membuat sumber daya, atau   menimpanya. Saat Anda menentukan   sumber daya URL baru.

Untuk sumber daya baru:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

Untuk menimpa sumber daya yang ada:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/

3480
2018-03-10 14:29



Anda dapat menemukan pernyataan di web yang mengatakan

Tidak juga benar.


Lebih baik memilih antara PUT dan POST berdasarkan idempoten aksi.

TARUH berarti menempatkan sumber daya - sepenuhnya menggantikan apa pun yang tersedia di URL yang diberikan dengan hal yang berbeda. Menurut definisi, PUT adalah idempoten. Lakukan sebanyak yang Anda suka, dan hasilnya sama. x=5 adalah idempoten. Anda dapat PUT sumber daya apakah sebelumnya ada, atau tidak (misalnya, Buat, atau Perbarui)!

POS memperbarui sumber daya, menambahkan sumber daya tambahan, atau menyebabkan perubahan. POST tidak idempoten, dengan cara itu x++ bukan idempoten.


Dengan argumen ini, PUT adalah untuk membuat ketika Anda tahu URL dari hal yang akan Anda buat. POST dapat digunakan untuk membuat saat Anda mengetahui URL "pabrik" atau pengelola untuk kategori hal yang ingin Anda buat.

begitu:

POST /expense-report

atau:

PUT  /expense-report/10929

1878
2018-04-22 14:55



  • POS ke URL menciptakan sumber daya anak di a server didefinisikan URL.
  • TARUH ke URL membuat / mengganti sumber daya secara keseluruhan di klien didefinisikan URL.
  • PATCH ke URL pembaruan bagian sumber daya di URL yang ditentukan oleh klien.

Spesifikasi yang relevan untuk PUT dan POST adalah RFC 2616 §9.5ff.

POST membuat sumber daya anak, jadi POST untuk /items menciptakan sumber daya yang hidup di bawah /items sumber. Misalnya. /items/1. Mengirim paket pos yang sama dua kali akan membuat dua sumber daya.

TARUH adalah untuk membuat atau mengganti sumber daya di a URL yang dikenal oleh klien.

Karena itu: TARUH hanya kandidat untuk CREATE di mana klien sudah tahu url sebelum sumber dibuat. Misalnya. /blogs/nigel/entry/when_to_use_post_vs_put sebagai judul digunakan sebagai kunci sumber daya

TARUH menggantikan sumber daya di url yang dikenal jika sudah ada, jadi mengirim permintaan yang sama dua kali tidak berpengaruh. Dengan kata lain, panggilan ke PUT adalah idempoten.

RFC berbunyi seperti ini:

Perbedaan mendasar antara permintaan POST dan PUT tercermin dalam arti yang berbeda dari Request-URI. URI dalam permintaan POST mengidentifikasi sumber daya yang akan menangani entitas terlampir. Sumber daya itu mungkin merupakan proses penerimaan data, gerbang ke beberapa protokol lain, atau entitas terpisah yang menerima anotasi. Sebaliknya, URI dalam permintaan PUT mengidentifikasi entitas terlampir dengan permintaan - agen pengguna tahu apa yang dimaksud URI dan server TIDAK HARUS berusaha untuk menerapkan permintaan ke beberapa sumber lain. Jika server menginginkan agar permintaan diterapkan ke URI yang berbeda,

catatan: PUT sebagian besar telah digunakan untuk memperbarui sumber daya (dengan menggantikannya secara keseluruhan), tetapi baru-baru ini ada gerakan untuk menggunakan PATCH untuk memperbarui sumber daya yang ada, karena PUT menetapkan bahwa itu menggantikan seluruh sumber daya. RFC 5789.


562
2018-04-07 05:52



Ringkasan:

Membuat:

Dapat dilakukan dengan PUT atau POST dengan cara berikut:

TARUH

Menciptakan ITU sumber daya baru dengan newResourceId sebagai pengidentifikasi, di bawah / sumber daya URI, atau koleksi.

PUT /resources/<newResourceId> HTTP/1.1 

POS

Menciptakan SEBUAH sumber daya baru di bawah / sumber daya URI, atau koleksi. Biasanya identifier dikembalikan oleh server.

POST /resources HTTP/1.1

Memperbarui:

Bisa hanya dilakukan dengan PUT dengan cara berikut:

TARUH

Perbarui sumber daya dengan existingResourceId sebagai pengidentifikasi, di bawah / sumber daya URI, atau koleksi.

PUT /resources/<existingResourceId> HTTP/1.1

Penjelasan:

Ketika berhadapan dengan REST dan URI sebagai umum, Anda punya umum pada kiri dan spesifik pada kanan. Itu obat generik biasanya disebut koleksi dan lebih banyak lagi spesifik barang bisa disebut sumber. Perhatikan bahwa a sumber dapat berisi koleksi.

Contoh:

<- generik - spesifik ->

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

Ketika Anda menggunakan POST Anda selalu mengacu pada a koleksi, jadi kapan pun Anda berkata:

POST /users HTTP/1.1

Anda memposting pengguna baru ke pengguna  koleksi.

Jika Anda terus mencoba sesuatu seperti ini:

POST /users/john HTTP/1.1

itu akan berfungsi, tetapi secara semantis Anda mengatakan bahwa Anda ingin menambahkan sumber daya ke john  koleksi di bawah pengguna  koleksi.

Setelah Anda menggunakan PUT, Anda mengacu pada a sumber atau satu item, mungkin di dalam koleksi. Jadi ketika Anda berkata:

PUT /users/john HTTP/1.1

Anda memberi tahu ke pembaruan server, atau membuat jika tidak ada, john  sumber di bawah pengguna  koleksi.

Spec:

Biarkan saya menyoroti beberapa bagian penting dari spesifikasi:

POS

Itu POS metode digunakan untuk meminta server asal menerima entitas terlampir dalam permintaan sebagai baru bawahan dari sumber daya yang diidentifikasi oleh Request-URI di Request-Line

Oleh karena itu, buat yang baru sumber pada suatu koleksi.

TARUH

Itu TARUH meminta metode yang entitas terlampir disimpan di bawah Request-URI yang disediakan. Jika Request-URI mengacu pada suatu sudah ada sumber daya, entitas tertutup HARUS dianggap sebagai versi modifikasi dari yang berada di server asal. Jika Request-URI tidak tidak menunjuk ke yang ada sumber daya, dan URI itu mampu didefinisikan sebagai baru sumber oleh agen pengguna yang meminta, server asal dapat membuat sumber daya dengan URI itu. "

Oleh karena itu, buat atau perbarui berdasarkan keberadaan sumber.

Referensi:


165
2017-08-14 22:47



Saya ingin menambahkan saran "pragmatis" saya. Gunakan PUT ketika Anda tahu "id" dimana objek yang Anda simpan dapat diambil. Menggunakan PUT tidak akan berfungsi dengan baik jika Anda perlu, katakanlah, basis data yang dihasilkan untuk dikembalikan agar Anda dapat melakukan pencarian atau pembaruan di masa mendatang.

Jadi: Untuk menyimpan pengguna yang ada, atau di mana klien menghasilkan id dan telah diverifikasi bahwa id itu unik:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

Jika tidak, gunakan POST untuk awalnya membuat objek, dan PUT untuk memperbarui objek:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

156
2018-01-15 19:59



POST berarti "buat baru" seperti pada "Ini adalah masukan untuk membuat pengguna, buat untuk saya".

PUT berarti "masukkan, ganti jika sudah ada" seperti pada "Ini adalah data untuk pengguna 5".

Anda POST ke example.com/users karena Anda belum mengetahui URL pengguna, Anda ingin server membuatnya.

Anda PUT to example.com/users/id karena Anda ingin mengganti / membuat spesifik pengguna.

POSTing dua kali dengan data yang sama berarti membuat dua pengguna identik dengan ID yang berbeda. PUTing dua kali dengan data yang sama menciptakan pengguna yang pertama dan memperbaruinya ke keadaan yang sama untuk kedua kalinya (tidak ada perubahan). Karena Anda berakhir dengan keadaan yang sama setelah PUT tidak peduli berapa kali Anda melakukan itu, itu dikatakan "sama kuat" setiap waktu - idempoten. Ini berguna untuk mencoba kembali permintaan secara otomatis. Tidak ada lagi 'apakah Anda yakin ingin mengirim ulang' saat Anda menekan tombol kembali pada browser.

Saran umum adalah menggunakan POST ketika Anda membutuhkan server untuk mengendalikan pembuatan sumber daya URL Anda. Gunakan PUT sebaliknya. Lebih suka PUT daripada POST.


145
2017-10-23 14:27



Gunakan POST untuk membuat, dan PUT untuk memperbarui. Begitulah cara Ruby on Rails melakukannya.

PUT    /items/1      #=> update
POST   /items        #=> create

105
2018-03-10 14:28



REST adalah a sangat konsep tingkat tinggi. Bahkan, itu bahkan tidak menyebutkan HTTP sama sekali!

Jika Anda memiliki keraguan tentang cara mengimplementasikan REST di HTTP, Anda selalu dapat melihat di Atom Publication Protocol (AtomPub) spesifikasi. AtomPub adalah standar untuk menulis RESTful webservices dengan HTTP yang dikembangkan oleh banyak tokoh HTTP dan REST, dengan beberapa masukan dari Roy Fielding, penemu REST dan (co-) penemu HTTP sendiri.

Bahkan, Anda mungkin bahkan dapat menggunakan AtomPub secara langsung. Meskipun keluar dari komunitas blogging, itu tidak dibatasi untuk blogging: itu adalah protokol umum untuk RESTfully berinteraksi dengan sewenang-wenang (bersarang) koleksi sumber daya sewenang-wenang melalui HTTP. Jika Anda dapat mewakili aplikasi Anda sebagai kumpulan sumber daya bersarang, maka Anda bisa menggunakan AtomPub dan tidak khawatir tentang apakah akan menggunakan PUT atau POST, apa Kode Status HTTP untuk kembali dan semua detail tersebut.

Inilah yang AtomPub katakan tentang penciptaan sumber daya (bagian 9.2):

Untuk menambahkan anggota ke Koleksi, klien mengirim permintaan POST ke URI Koleksi.


58
2018-03-10 15:27



Keputusan apakah akan menggunakan PUT atau POST untuk membuat sumber daya di server dengan HTTP + REST API didasarkan pada siapa yang memiliki struktur URL. Setelah klien tahu, atau berpartisipasi dalam mendefinisikan, struct URL adalah kopling yang tidak perlu mirip dengan kopling yang tidak diinginkan yang muncul dari SOA. Escaping jenis kopling adalah alasan REST sangat populer. Karena itu, metode yang tepat untuk digunakan adalah POST. Ada pengecualian untuk aturan ini dan mereka terjadi ketika klien ingin mempertahankan kontrol atas struktur lokasi dari sumber daya yang dipaksakannya. Ini jarang dan kemungkinan berarti ada hal lain yang salah.

Pada titik ini beberapa orang akan berpendapat bahwa jika RESTful-URL's digunakan, klien tidak tahu URL sumber daya dan karena itu PUT dapat diterima. Lagi pula, inilah sebabnya mengapa kanonik, normal, Ruby on Rails, URL Django penting, lihat API Twitter ... bla bla bla. Orang-orang itu perlu mengerti tidak ada yang namanya URL Istirahat dan itu Roy Fielding sendiri menyatakan hal itu:

A REST API tidak boleh mendefinisikan nama atau hierarki sumber daya tetap (an   kopling jelas dari klien dan server). Server harus memiliki kebebasan   untuk mengontrol namespace mereka sendiri. Sebaliknya, izinkan server untuk menginstruksikan   klien tentang cara membuat URI yang sesuai, seperti yang dilakukan dalam HTML   formulir dan template URI, dengan menentukan instruksi tersebut dalam media   jenis dan hubungan tautan. [Kegagalan di sini menyiratkan bahwa klien   dengan asumsi struktur sumber daya karena informasi band yang keluar, seperti   standar khusus domain, yang setara dengan data yang berorientasi   Kopling fungsional RPC].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

Ide a RESTful-URL sebenarnya adalah pelanggaran REST karena server bertanggung jawab atas struktur URL dan harus bebas memutuskan cara menggunakannya untuk menghindari penggandengan. Jika ini membingungkan Anda membaca tentang pentingnya penemuan diri pada desain API.

Menggunakan POST untuk membuat sumber daya hadir dengan pertimbangan desain karena POST tidak idempoten. Ini berarti bahwa mengulangi POST beberapa kali tidak menjamin perilaku yang sama setiap kali. Ini membuat orang takut menggunakan PUT untuk membuat sumber daya padahal seharusnya tidak. Mereka tahu itu salah (POST adalah untuk CREATE) tetapi mereka tetap melakukannya karena mereka tidak tahu bagaimana memecahkan masalah ini. Kekhawatiran ini ditunjukkan dalam situasi berikut:

  1. Klien mengirim sumber daya baru ke server.
  2. Server memproses permintaan dan mengirim tanggapan.
  3. Klien tidak pernah menerima respons.
  4. Server tidak menyadari bahwa klien belum menerima respons.
  5. Klien tidak memiliki URL untuk sumber daya (oleh karena itu PUT bukan merupakan opsi) dan mengulangi POST.
  6. POST tidak idempoten dan server ...

Langkah 6 adalah di mana orang biasanya bingung tentang apa yang harus dilakukan. Namun, tidak ada alasan untuk membuat kludge untuk menyelesaikan masalah ini. Sebagai gantinya, HTTP dapat digunakan sebagaimana ditentukan dalam RFC 2616 dan server membalas:

10.4.10 409 Konflik

Permintaan tidak dapat diselesaikan karena konflik dengan arus   keadaan sumber daya. Kode ini hanya diizinkan dalam situasi di mana   diharapkan bahwa pengguna mungkin dapat menyelesaikan konflik dan   kirim kembali permintaan. Badan respon HARUS cukup disertakan

informasi bagi pengguna untuk mengenali sumber konflik.   Idealnya, entitas respon akan menyertakan informasi yang cukup untuk   pengguna atau agen pengguna untuk memperbaiki masalah; Namun, itu mungkin tidak   mungkin dan tidak diperlukan.

Konflik paling mungkin terjadi sebagai tanggapan atas permintaan PUT. Untuk   Misalnya, jika versi digunakan dan entitas menjadi PUT   termasuk perubahan ke sumber daya yang bertentangan dengan yang dibuat oleh   permintaan sebelumnya (pihak ketiga), server mungkin menggunakan tanggapan 409   untuk menunjukkan bahwa itu tidak dapat menyelesaikan permintaan. Dalam hal ini, itu   entitas respon kemungkinan akan berisi daftar perbedaan antara   dua versi dalam format yang ditentukan oleh Respons Content-Type.

Membalas dengan kode status 409 Konflik adalah jalan yang benar karena:

  • Melakukan POST data yang memiliki ID yang cocok dengan sumber daya yang sudah ada dalam sistem adalah "konflik dengan status sumber daya saat ini."
  • Karena bagian yang penting adalah agar klien memahami server memiliki sumber daya dan untuk mengambil tindakan yang tepat. Ini adalah “situasi di mana diharapkan pengguna mungkin dapat menyelesaikan konflik dan mengirimkan kembali permintaan.”
  • Tanggapan yang berisi URL sumber daya dengan ID yang bertentangan dan prakondisi yang sesuai untuk sumber daya akan memberikan "cukup informasi bagi pengguna atau agen pengguna untuk memperbaiki masalah" yang merupakan kasus ideal per RFC 2616.

Perbarui berdasarkan rilis RFC 7231 untuk Menggantikan 2616

RFC 7231 dirancang untuk menggantikan 2616 dan di Bagian 4.3.3 menjelaskan tanggapan yang mungkin diikuti untuk suatu POST

Jika hasil pemrosesan POST akan setara dengan   representasi dari sumber yang ada, server asal MUNGKIN redirect   agen pengguna ke sumber daya itu dengan mengirimkan respons 303 (Lihat Lainnya)   dengan pengidentifikasi sumber daya yang ada di bidang Lokasi. Ini   memiliki manfaat memberikan agen pengguna pengidentifikasi sumber daya   dan mentransfer representasi melalui metode yang lebih bisa diterima   caching bersama, meskipun dengan biaya permintaan tambahan jika pengguna   agen belum memiliki representasi cache.

Sekarang mungkin tergoda untuk hanya mengembalikan 303 jika POST diulang. Namun, yang terjadi justru sebaliknya. Mengembalikan 303 hanya akan masuk akal jika beberapa membuat permintaan (membuat sumber daya berbeda) mengembalikan konten yang sama. Contohnya adalah "terima kasih telah mengirimkan pesan permintaan Anda" bahwa klien tidak perlu mengunduh ulang setiap kali. RFC 7231 masih mempertahankan dalam bagian 4.2.2 bahwa POST tidak menjadi idempoten dan terus mempertahankan bahwa POST harus digunakan untuk membuat.

Untuk informasi lebih lanjut tentang ini, baca ini artikel.


54
2017-10-29 23:00