HTTP POST dengan parameter permintaan URL - ide bagus atau tidak? [Tutup]

451

Saya merancang API untuk membahas HTTP dan saya bertanya-tanya apakah menggunakan perintah HTTP POST, tetapi dengan parameter kueri URL saja dan tanpa badan permintaan, adalah cara yang baik untuk melakukannya.

Pertimbangan:

  • "Desain Web yang Baik" membutuhkan tindakan non-idempoten untuk dikirim melalui POST. Ini adalah tindakan non-idempoten.
  • Lebih mudah untuk mengembangkan dan men-debug aplikasi ini ketika parameter permintaan ada di URL.
  • API tidak dimaksudkan untuk penggunaan luas.
  • Sepertinya membuat permintaan POST tanpa badan akan membutuhkan lebih banyak pekerjaan, mis. Content-Length: 0Tajuk harus ditambahkan secara eksplisit.
  • Bagi saya sepertinya juga POST tanpa badan sedikit bertentangan dengan harapan sebagian besar pengembang dan HTTP frameworks.

Apakah ada jebakan atau keuntungan lagi untuk mengirim parameter pada permintaan POST melalui permintaan URL daripada badan permintaan?

Sunting: Alasan mengapa hal ini dipertimbangkan adalah karena operasinya tidak idempoten dan memiliki efek samping selain pengambilan. Lihat spesifikasi HTTP :

Secara khusus, konvensi telah ditetapkan bahwa metode GET dan HEAD TIDAK HARUS memiliki signifikansi untuk mengambil tindakan selain pengambilan. Metode-metode ini harus dianggap "aman". Ini memungkinkan agen pengguna untuk mewakili metode lain, seperti POST, PUT dan DELETE, dengan cara khusus, sehingga pengguna dibuat sadar akan fakta bahwa tindakan yang mungkin tidak aman sedang diminta.

...

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. Metode DAPATKAN, KEPALA, PUT, dan HAPUS berbagi properti ini. Juga, metode OPSI dan LALU TIDAK HARUS memiliki efek samping, dan pada dasarnya idempoten.

Steven Huwig
sumber
11
Mengapa menggunakan POST sama sekali jika Anda tidak akan memberikan data dalam tubuh?
Sunny Milenov
114
Karena operasinya tidak idempoten.
Steven Huwig
20
@Jared, perhatikan bahwa kata "REST" tidak muncul dalam pertanyaan ini sejak 2,5 tahun yang lalu. :) Spesifikasi HTTP tentang idempotensi berlaku terlepas dari apa rasanya arsitektur bulan ini untuk layanan web. Untungnya, sistem yang dirancang untuk proxy oleh API ini telah dianggap usang.
Steven Huwig
5
Karena log server tidak merekam parameter POST, tetapi mereka mencatat string kueri. Jauh lebih mudah untuk menjalankan serangkaian permintaan tanpa menginstruksikannya di browser, dan kemudian melihat traceback, daripada mengkliknya. Juga API bukan browser-ke-server, melainkan server-ke-server. Yang paling penting, semua urusan tetap dilakukan. :)
Steven Huwig
13
Bagi siapa pun yang tidak tahu apa arti idempoten: | restapitutorial.com/lessons/idempotency.html
Christopher Grigg

Jawaban:

259

Jika tindakan Anda tidak idempoten, maka Anda HARUS menggunakan POST. Jika tidak, Anda hanya meminta masalah di telepon. GET, PUTDan DELETEmetode yang diperlukan untuk menjadi idempoten. Bayangkan apa yang akan terjadi dalam aplikasi Anda jika klien melakukan pre-fetching setiap kemungkinanGET permintaan layanan Anda - jika ini akan menyebabkan efek samping yang terlihat oleh klien, maka ada sesuatu yang salah.

Saya setuju bahwa mengirim a POST dengan string kueri tetapi tanpa badan tampaknya aneh, tapi saya pikir itu bisa sesuai dalam beberapa situasi.

Pikirkan bagian permintaan URL sebagai perintah ke sumber daya untuk membatasi ruang lingkup permintaan saat ini. Biasanya, string kueri digunakan untuk mengurutkan atau memfilter GETpermintaan (seperti ?page=1&sort=title) tapi saya rasa masuk akal POSTjuga untuk membatasi ruang lingkup (mungkin seperti ?action=delete&id=5).

Don McCaughey
sumber
4
Saya memilih jawaban ini untuk kasus khusus ini, tetapi saya pikir argumen R. Bemrose menarik untuk API publik.
Steven Huwig
4
Saya kira jawabannya tidak benar. Jika Anda tahu parameter URL untuk postingan formulir Anda ketika halaman HTML dikirim ke klien, Anda bisa menempelkan parameter URL itu ke atribut tindakan form, jika tidak JavaScript dapat mengatur parameter URL ketika formulir dikirimkan.
Don McCaughey
3
bagaimana dengan posting file xml ke url dengan parameter kueri? Apakah itu mungkin?
OpenCoderX
3
Contoh lain: data permintaan bisa di entitas http, sedangkan format respons yang diminta diteruskan dalam parameter kueri ( /action?response_format=json)
rds
4
+1 belajar sesuatu hari ini. Hapus memiliki teknis untuk menjadi idempoten. Jika objek tersebut benar-benar dihapus maka Anda akan mendapatkan 404 yang tidak ditemukan sehingga server akan memiliki status yang sama tetapi responsnya akan berbeda. Lihat Gambar Sapi: restapitutorial.com/lessons/idempotency.html
JPK
131

Semua orang benar: tetap dengan POST untuk permintaan non-idempoten.

Bagaimana dengan menggunakan string kueri URI dan konten permintaan? Yah itu HTTP yang valid (lihat catatan 1), jadi mengapa tidak ?!

Ini juga sangat logis: URL, termasuk bagian string kueri, untuk mencari sumber daya. Sedangkan kata kerja metode HTTP (POST - dan konten permintaan opsional) adalah untuk menentukan tindakan, atau apa yang harus dilakukan sumber daya. Itu harus menjadi perhatian ortogonal. (Tapi, itu bukan masalah orthogonal yang indah untuk kasus khusus ContentType = application / x-www-form-urlencoded, lihat catatan 2 di bawah.)

Catatan 1: Spesifikasi HTTP (1.1) tidak menyatakan bahwa parameter kueri dan konten saling eksklusif untuk server HTTP yang menerima permintaan POST atau PUT. Jadi setiap server bebas untuk menerima keduanya. Yaitu jika Anda menulis server tidak ada yang menghentikan Anda memilih untuk menerima keduanya (kecuali mungkin kerangka kerja yang tidak fleksibel). Secara umum, server dapat menafsirkan string kueri sesuai dengan aturan apa pun yang diinginkannya. Ia bahkan bisa menafsirkannya dengan logika kondisional yang merujuk ke tajuk lain seperti Jenis-Konten juga, yang mengarah ke Catatan 2:

Catatan 2: jika browser web adalah cara utama orang mengakses aplikasi web Anda, dan aplikasi / x-www-form-urlencoded adalah Tipe-Konten yang mereka posting, maka Anda harus mengikuti aturan untuk Tipe-Konten tersebut. Dan aturan untuk aplikasi / x-www-form-urlencoded jauh lebih spesifik (dan terus terang, tidak biasa): dalam hal ini Anda harus menafsirkan URI sebagai seperangkat parameter, dan bukan lokasi sumber daya. [Ini adalah poin kegunaan yang sama yang diangkat Powerlord; bahwa mungkin sulit untuk menggunakan formulir web untuk mengirim konten ke server Anda. Hanya menjelaskan sedikit berbeda.]

Catatan 3: untuk apa sebenarnya string permintaan? RFC 3986 mendefinisikan string kueri HTTP sebagai bagian URI yang berfungsi sebagai cara non-hierarkis untuk menemukan sumber daya.

Jika pembaca menanyakan pertanyaan ini, ingin tanyakan apa itu arsitektur RESTful yang bagus: pola arsitektur RESTful tidak memerlukan skema URI untuk bekerja dengan cara tertentu. Arsitektur RESTful menyangkut dirinya sendiri dengan sifat-sifat lain dari sistem, seperti cacheability sumber daya, desain sumber daya itu sendiri (perilaku, kemampuan, dan representasi mereka), dan apakah idempoten terpenuhi. Atau dengan kata lain, mencapai desain yang sangat kompatibel dengan protokol HTTP dan serangkaian kata kerja metode HTTP. :-) (Dengan kata lain, arsitektur RESTful tidak terlalu menentukan bagaimana sumber daya berada .)

Catatan akhir: kadang-kadang parameter kueri digunakan untuk hal-hal lain lagi, yang bukan mencari sumber daya atau mengkode konten. Pernah melihat parameter kueri seperti 'PUT = true' atau 'POST = true'? Ini adalah solusi untuk peramban yang tidak memungkinkan Anda untuk menggunakan metode PUT dan POST. Sementara parameter tersebut dilihat sebagai bagian dari query string URL (pada kawat), saya berpendapat bahwa mereka bukan bagian dari query URL dalam roh .

Tim Lovell-Smith
sumber
66

Anda ingin alasan? Ini dia:

Formulir web tidak dapat digunakan untuk mengirim permintaan ke halaman yang menggunakan campuran GET dan POST. Jika Anda mengatur metode formulir ke GET, semua parameter ada di string kueri. Jika Anda mengatur metode formulir ke POST, semua parameter ada di badan permintaan.

Sumber: HTML 4.01 standar, bagian 17.13 Pengajuan Formulir

Powerlord
sumber
10
Itu argumen yang layak, tapi saya pikir implementasi Javascript browser modern semacam membuatnya menjadi titik diperdebatkan. Saya akan memikirkannya - itu menarik dalam cara pemeriksaan di masa depan. Hanya karena saya tidak menggunakan formulir untuk itu sekarang tidak berarti saya tidak akan mau nanti.
Steven Huwig
9
Memadukan GET dengan POST hanyalah ide yang sangat buruk - sangat memecah HTTP dan tanpa alasan yang bagus.
aehlke
6
Cuplikan itu tidak muncul pada halaman yang Anda tautkan
Gareth
40
Benar, tetapi atribut metode hanya mendefinisikan bagaimana "kumpulan data formulir" dimasukkan dalam permintaan. Ketika methodPOST, tidak disebutkan mengubah URI di formulir action. Dan URI mana saja tentu saja sudah mengandung bagian string kueri.
Gareth
16
@Powerlord Ini salah. Cobalah mengatur formulir untuk POST dengan tindakan misalnya. /Books?bookCode=1234. Server web akan mendapatkan formulir POST vars dan string kueri.
Jez
9

Dari sudut pandang terprogram, untuk klien itu mengemas parameter dan menambahkannya ke url dan melakukan POST vs. GET. Di sisi server, ia mengevaluasi parameter masuk dari querystring bukan byte yang diposting. Pada dasarnya, ini sebuah pencucian.

Di mana mungkin ada kelebihan / kekurangan mungkin dalam cara platform klien tertentu bekerja dengan rutin POST dan GET dalam tumpukan jaringan mereka, serta bagaimana server web menangani permintaan tersebut. Bergantung pada implementasi Anda, satu pendekatan mungkin lebih efisien daripada yang lain. Mengetahui hal itu akan memandu keputusan Anda di sini.

Meskipun demikian, dari sudut pandang programmer, saya lebih suka mengizinkan POST dengan semua parameter di tubuh, atau GET dengan semua param di url, dan secara eksplisit mengabaikan parameter url dengan permintaan POST. Ini menghindari kebingungan.

jro
sumber
8

Saya pikir masih cukup tenang untuk memiliki argumen permintaan yang mengidentifikasi sumber daya di URL sambil menjaga muatan konten terbatas pada badan POST. Ini tampaknya memisahkan pertimbangan "Apa yang saya kirim?" versus "Kepada siapa saya mengirimkannya?".

swizzcheez
sumber
5
Pertanyaannya bukan tentang REST.
Steven Huwig
3
@ user359996 Tidak semua API HTTP tenang. Bahkan, sebagian besar API yang mengklaim itu sebenarnya tidak. Juga, fakta yang menyenangkan, REST juga bukan hanya HTTP.
Alec Mev
4

The SISA kamp memiliki beberapa prinsip yang bisa kita gunakan untuk membakukan cara kita menggunakan HTTP kata kerja. Ini sangat membantu ketika membangun RESTful API seperti yang Anda lakukan.

Singkatnya: GET harus Read Only yaitu tidak berpengaruh pada keadaan server. POST digunakan untuk membuat sumber daya di server. PUT digunakan untuk memperbarui atau membuat sumber daya. HAPUS digunakan untuk menghapus sumber daya.

Dengan kata lain, jika tindakan API Anda mengubah status server, REST menyarankan kami untuk menggunakan POST / PUT / DELETE, tetapi jangan GET.

Agen pengguna biasanya mengerti bahwa melakukan beberapa POST itu buruk dan akan memperingatkannya, karena maksud POST adalah mengubah status server (mis. Membayar barang saat checkout), dan Anda mungkin tidak ingin melakukannya dua kali!

Bandingkan dengan GET yang dapat Anda lakukan sesering mungkin (idempoten).

berlayar
sumber
13
Kamp REST mengatakan Anda harus menggunakan HTTP sebagaimana didefinisikan dalam spesifikasi HTTP. yaitu RFC2616 Tidak lebih, tidak kurang.
Darrel Miller
1
@Darrel Merujuk ibm.com/developerworks/webservices/library/ws-restful : REST meminta pengembang untuk menggunakan metode HTTP secara eksplisit dan dengan cara yang konsisten dengan definisi protokol. Prinsip desain REST dasar ini menetapkan pemetaan satu-ke-satu antara membuat, membaca, memperbarui, dan menghapus operasi (CRUD) dan metode HTTP. Menurut pemetaan ini: Untuk membuat sumber daya di server, gunakan POST. Untuk mengambil sumber daya, gunakan GET. Untuk mengubah status sumber daya atau memperbaruinya, gunakan PUT. Untuk menghapus atau menghapus sumber daya, gunakan DELETE.
berlayar
5
Maaf tapi itu salah besar. REST membutuhkan kepatuhan pada antarmuka yang seragam. Jika Anda menggunakan HTTP maka antarmuka seragam tersebut didefinisikan sebagian oleh RFC 2616. Dalam spesifikasi tersebut, tidak ada pemetaan satu-ke-satu antara membuat, membaca, memperbarui, dan menghapus dan metode HTTP.
Darrel Miller
3
DAPATKAN dan HAPUS peta dengan cukup baik untuk Dibaca dan Dihapus dalam CRUD, tetapi menggunakan PUT / POST untuk Pembaruan dan Pembuatan tidak semudah itu. Lihat stackoverflow.com/questions/630453/put-vs-post-in-rest
dcstraw
5
Melihat kembali ini 6 tahun kemudian, dan mengingat bahwa pertanyaannya telah dilihat ~ 100rb kali, saya merasa layak untuk memasukkan pembaruan kecil. Darrel benar menurut definisi Fielding tentang REST ( ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm ) - tidak disebutkan pemetaan pemetaan kata kerja HTTP ke CRUD. Saran pengembang IBM (tautan dalam komentar di atas) mencerminkan praktik umum dalam mengimplementasikan RESTful API, bukan definisi Fielding tentang REST.
berlayar
-13

Saya setuju - mungkin lebih aman menggunakan permintaan GET jika Anda hanya meneruskan data di URL dan tidak di dalam tubuh. Lihat pertanyaan serupa ini untuk beberapa tampilan tambahan pada keseluruhan konsep POST + GET.

Marc Novakowski
sumber
17
Jika operasi memiliki efek samping, maka tentu saja tidak 'aman' untuk menggunakan metode GET karena browser menganggap semua GET adalah idempoten.
dcstraw
Mesin pencari juga mengonversinya dalam mimpi buruk, karena Google akan dengan aman "mengklik" semua tautan dengan permintaan GET, tetapi akan menghilangkan yang lainnya. Tidak begitu aman meninggalkan layanan yang crawler tidak bersalah dapat menghapus database secara tidak sengaja.
Alejandro