Mengapa HTTP tidak memiliki pengalihan POST?

162

Pengalihan HTTP dilakukan melalui kode HTTP 301, dan 302 (mungkin juga kode lain) dan bidang tajuk yang dikenal sebagai "Lokasi" yang memiliki alamat tempat baru untuk dituju. Namun, browser selalu mengirim permintaan "GET" ke URL itu.

Namun, berkali-kali Anda perlu mengarahkan pengguna ke domain lain melalui POST (misalnya pembayaran bank). Ini adalah skenario umum, dan benar-benar persyaratan. Adakah yang tahu mengapa persyaratan umum seperti itu diabaikan dalam spesifikasi HTTP? Solusinya adalah mengirim formulir (dengan parameter di bidang tersembunyi) dengan tindakan yang ditetapkan ke lokasi target (nilai bidang header Lokasi ) dan gunakan setTimeoutuntuk mengirimkan formulir ke lokasi target.

Saeed Neamati
sumber
1
Apakah kode status 307 yang Anda cari? Lihat jawaban saya di bawah ini.
David Ruttka

Jawaban:

180

Dalam HTTP 1.1, sebenarnya ada kode status ( 307 ) yang menunjukkan bahwa permintaan harus diulang menggunakan metode yang sama dan memposting data .

Seperti yang dikatakan orang lain, ada potensi penyalahgunaan di sini yang mungkin menjadi alasan mengapa banyak kerangka berpegang pada 301 dan 302 dalam abstraksi mereka. Namun, dengan pemahaman yang tepat dan penggunaan yang bertanggung jawab, Anda harus dapat mencapai apa yang Anda cari.

Perhatikan bahwa sesuai dengan spesifikasi W3.org , ketika METHODtidak HEADatau GET, agen pengguna harus meminta pengguna sebelum menjalankan kembali permintaan di lokasi baru. Anda juga harus memberikan catatan dan mekanisme mundur untuk pengguna jika agen pengguna lama tidak yakin apa yang harus dilakukan dengan 307.

Menggunakan formulir ini:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

Dan memiliki Test307.aspx cukup mengembalikan 307 dengan Location: http://google.com , Chrome 13 dan Fiddler mengonfirmasi bahwa "test = the test" memang diposting ke Google. Tentu saja respons selanjutnya adalah 405 karena Google tidak mengizinkan POST, tetapi ini menunjukkan mekanika.

Untuk informasi lebih lanjut, lihat Daftar kode status HTTP dan spesifikasi W3.org .

307 Pengalihan Sementara (sejak HTTP / 1.1) Dalam kesempatan ini, permintaan harus diulang dengan URI lain, tetapi permintaan di masa mendatang masih dapat menggunakan URI asli. 2 Berbeda dengan 303, metode permintaan tidak boleh diubah saat mengeluarkan kembali permintaan asli. Misalnya, permintaan POST harus diulang menggunakan permintaan POST lain.

David Ruttka
sumber
2
@ Davidviduttka, Apa dukungan browser di alam liar ?
Pacerier
5
@DavidRuttka Anda mungkin ingin memperbarui jawaban Anda untuk memperhitungkan rfc7231 (obsoletes rfc2616). Meminta pengguna didasarkan pada persyaratan di rfc2616. Persyaratan ini dijatuhkan di rfc7231 dan rfc7231 juga memperkenalkan persyaratan bahwa 307 redirect tidak boleh mengubah metode permintaan (yang Anda sebutkan dalam kutipan Anda di akhir jawaban Anda).
nibarius
Perhatikan bahwa menurut tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "Kode pengalihan HTTP 301-306 TIDAK HARUS digunakan kecuali penyedia layanan sadar bahwa klien sebenarnya adalah pengguna- "Jadi sepertinya layanan RESTful harus menggunakan 308 bukannya 301. Namun ini hanya konsep.
Bruce Adams
49

Saya menemukan penjelasan yang bagus di halaman ini di sini .

Situasi paling sederhana di WWW adalah transaksi "idempoten", yaitu transaksi yang dapat diulang tanpa menimbulkan kerugian. Ini biasanya transaksi "GET", baik karena mereka mengambil referensi langsung URL (misalnya href = atau src = atribut dalam HTML), atau karena mereka adalah pengiriman formulir menggunakan metode GET. Mengarahkan transaksi semacam itu sangat mudah, dan tidak ada pertanyaan yang diajukan: klien menerima respons pengalihan, termasuk header Lokasi: yang menentukan URL baru, dan klien bereaksi terhadapnya dengan menerbitkan kembali transaksi ke URL baru. Ada perbedaan antara kode status 30x berbeda yang terkait dengan pengalihan ini dalam cacheability tersirat mereka, tetapi sebaliknya mereka pada dasarnya serupa (301 dan 302) dalam menanggapi permintaan GET.

Transaksi POST berbeda, karena pada prinsipnya didefinisikan sebagai non-idempoten (seperti memesan pizza, memberikan suara atau apa pun) dan tidak boleh diulang secara sewenang-wenang.

Spesifikasi protokol HTTP dirancang untuk mempertimbangkan perbedaan ini: metode GET didefinisikan sebagai inheren idempoten, sedangkan metode POST didefinisikan, setidaknya secara potensial, non-idempoten; spesifikasi meminta sejumlah tindakan pencegahan yang harus diambil oleh agen klien (seperti browser) untuk melindungi pengguna terhadap secara tidak sengaja (kembali) mengirimkan transaksi POST yang tidak mereka maksudkan, atau mengirimkan POST ke dalam konteks yang tidak mereka inginkan .

Meskipun saya bukan penggemar membatasi pengguna secara teknis untuk mencegah mereka menyebabkan kekacauan yang tidak diinginkan atau melakukan kerusakan yang tidak diinginkan pada aplikasi mereka, saya dapat memahami intinya dan itu masuk akal.

Elang
sumber
sebagian besar alasan masuk ke hari-hari ketika intertubes lambat dan tidak dapat diandalkan (yang masih ada di banyak lokasi di dunia). Saya ingat dengan jelas ketika saya menggunakan dial up dan secara acak akan terputus setiap kali orang lain mengangkat telepon. Lebih baik memuat ulang halaman dan melihat status server itu daripada mengirim ulang hal-hal dan berisiko melakukan tindakan yang sama dua kali.
zzzzBov
@ Falcon, Apakah meningkatkan "konter pengunjung" dianggap non-idempoten? Jika demikian, hampir tidak ada situs web hari ini melakukan GET yang idempoten ...
Pacerier
@Pacerier: Biasanya idempoten diartikan sebagai "idempoten dengan cara yang bermakna", misalnya, membeli barang yang sama dua kali, tidak mencatat dua kunjungan. Kalau tidak, Anda akan benar. Tapi sungguh, spek itu seharusnya mengharuskan server menjadi idempoten secara bermakna jika diperlukan, seperti menyematkan ID di halaman untuk mencegah duplikasi - tidak mengharuskan browser untuk mengajukan pertanyaan kepada pengguna, mereka tidak memiliki cara menjawab dengan akurasi. Apapun, mencegah pengalihan POST tidak mempengaruhi idempotensi; itu hanya sebuah pesan yang mengatakan target permintaan sebenarnya ada di sana.
Lawrence Dol
Saya tidak melihat bagaimana ini masuk akal untuk alasan ini. Katakan saya di situs web bank Chase dan saya mengirimkan formulir. Saya sudah setuju / mempercayai mereka. Jadi jika mereka harus mengarahkan ulang data itu ke halaman lain, mengapa saya harus setuju lagi. Atau contoh lain, Katakan saya orang yang mematikan JavaScript secara default. Suatu hari saya mengisi aplikasi hipotek online dan ketika saya mengirimkan formulir itu ada kesalahan. Akan lebih bagus jika aplikasi dapat mengarahkan (dengan POST) ke halaman yang baru saja saya isi untuk mengisi data sebelumnya.
B01
@Flacon, saya perlu bukti bahwa membatasi pengalihan dengan POST dapat mencegah kekacauan dalam hal apa pun. Karena saya pertama kali harus mempercayai aplikasi dengan data saya, mereka dapat melakukan apa pun yang mereka inginkan dengan mereka setelah mereka memiliki data. Dan saya tidak berpikir bahwa arahan ulang lebih rentan daripada permintaan dengan POST.
B01
3

GET (dan beberapa metode lain) didefinisikan sebagai 'AMAN' dalam spesifikasi http ( RFC 2616 ):

9.1.1 Metode Aman

Para pelaksana harus menyadari bahwa perangkat lunak tersebut mewakili pengguna dalam interaksi mereka melalui Internet, dan harus berhati-hati agar pengguna mengetahui tindakan apa pun yang mungkin mereka ambil yang mungkin memiliki arti penting yang tidak terduga bagi diri mereka sendiri atau orang lain.

Secara khusus, konvensi telah ditetapkan bahwa metode GET dan HEAD TIDAK HARUS memiliki signifikansi 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.

Secara alami, tidak mungkin untuk memastikan bahwa server tidak menghasilkan efek samping sebagai akibat dari melakukan permintaan GET; pada kenyataannya, beberapa sumber daya dinamis menganggap itu sebagai fitur. Perbedaan penting di sini adalah bahwa pengguna tidak meminta efek samping, sehingga tidak dapat dimintai pertanggungjawaban atas efek sampingnya.

Ini berarti bahwa permintaan GET tidak boleh memiliki konsekuensi serius bagi pengguna, selain melihat sesuatu yang mungkin tidak ingin mereka lihat, tetapi permintaan POST dapat mengubah sumber daya yang penting bagi mereka, atau orang lain.

Meskipun ini telah berubah dengan JavaScript, secara tradisional ada antarmuka pengguna yang berbeda - pengguna dapat memicu permintaan GET dengan mengklik tautan, tetapi harus mengisi formulir untuk memicu permintaan POST. Saya pikir para desainer HTTP tertarik untuk mempertahankan perbedaan antara metode yang aman dan tidak aman.

Saya juga tidak berpikir perlu untuk mengarahkan ke POST. Setiap tindakan yang perlu dilakukan mungkin dapat dilakukan dengan memanggil fungsi dalam kode sisi server, atau jika perlu terjadi pada server yang berbeda maka alih-alih mengirim pengalihan yang berisi URL untuk browser ke POST ke, server bisa membuat permintaan ke server itu sendiri, bertindak seperti proxy untuk pengguna.

bdsl
sumber