Fragmen URL dan 302 pengalihan

137

Sudah diketahui dengan baik bahwa fragmen URL (bagian setelah #) tidak dikirim ke server.

Saya bertanya-tanya bagaimana fragmen bekerja ketika pengalihan server (melalui status HTTP 302 dan Location:header) terlibat.

Pertanyaan saya sebenarnya dua kali lipat:

  1. Jika URL asli memiliki fragmen ( /original.php#foo), dan pengalihan dibuat ke /new.php, apakah bagian fragmen dari URL asli hilang begitu saja? Atau apakah terkadang diterapkan ke URL baru?
    Apakah URL baru akan pernah ada /new.php#foodalam kasus ini?

  2. Terlepas dari URL aslinya, jika server mengalihkan ke URL baru dengan fragment ( /new.php#foo), akankah fragmen tersebut "dihormati"? Atau apakah server benar-benar tidak memiliki bisnis yang mengganggu fragmen sama sekali - dan akankah browser mengabaikannya hanya dengan membuka /new.php??

levik
sumber
1
Di sini Anda dapat menemukan spesifikasi W3C: w3.org/TR/cuap#uri klausul 4.1. fragmen harus disimpan saat pengalihan.
Marcin

Jawaban:

136

Pembaruan 2014-Jun-27 :

RFC 7231, Hypertext Transfer Protocol (HTTP / 1.1): Semantik dan Konten , telah diterbitkan sebagai STANDAR YANG DIUSULKAN. Dari Changelog :

Sintaksis bidang header Lokasi telah diubah untuk mengizinkan semua referensi URI, termasuk referensi relatif dan fragmen, bersama dengan beberapa klarifikasi tentang kapan penggunaan fragmen tidak sesuai. (Bagian 7.1.2)

Poin-poin penting dari Bagian 7.1.2. Lokasi :

Jika nilai Lokasi yang diberikan dalam respons 3xx (Redirection) tidak memiliki komponen fragmen, agen pengguna HARUS memproses pengalihan seolah-olah nilai tersebut mewarisi komponen fragmen dari referensi URI yang digunakan untuk menghasilkan target permintaan (yaitu, redirection mewarisi fragmen referensi asli, jika ada).

Misalnya, permintaan GET yang dibuat untuk referensi URI " http://www.example.org/~tim " dapat menghasilkan respons 303 (Lihat Lainnya) yang berisi bidang header:

Location: /People.html#tim

yang menunjukkan bahwa agen pengguna mengalihkan ke " http://www.example.org/People.html#tim "

Demikian pula, permintaan GET yang dibuat untuk referensi URI " http://www.example.org/index.html#larry " dapat menghasilkan respons 301 (Dipindahkan Secara Permanen) yang berisi bidang header:

Location: http://www.example.net/index.html

yang menunjukkan bahwa agen pengguna mengalihkan ke " http://www.example.net/index.html#larry ", dengan mempertahankan pengenal fragmen asli.

Ini harus menjawab pertanyaan Anda dengan jelas.

Perbarui END

ini adalah masalah terbuka (tidak ditentukan) dengan spesifikasi HTTP saat ini . hal ini dibahas dalam 2 masalah kelompok kerja httpbis IETF :

# 6 memungkinkan fragmen di Locationheader. # 43 mengatakan ini:

Saya baru saja menguji ini dengan berbagai browser.

  • Firefox dan Safari menggunakan fragmen di header lokasi.
  • Opera menggunakan fragmen dari URI sumber, jika ada, jika tidak, fragmen dari lokasi pengalihan
  • IE (8) mengabaikan fragmen di URI lokasi, sehingga akan menggunakan fragmen dari URI sumber, jika ada

Usul:

"Catatan: perilaku saat pengidentifikasi fragmen dari URI asli dan pengalihan perlu digabungkan tidak ditentukan; Agen Pengguna saat ini memang berbeda dalam hal apa yang diutamakan fragmen."

[...]

Tampaknya IE8 tidak menggunakan idenfitier fragmen dari Location(perilaku yang saya lihat mungkin terbatas pada localhost).

Jadi kami tampaknya memiliki perilaku yang konsisten untuk Safari / IE / Firefox / Chrome (baru saja diuji), di mana fragmen dari header Lokasi digunakan, apa pun URI aslinya.

Oleh karena itu saya mengubah proposal saya ke dokumen yang sebagai perilaku yang diharapkan.

ini mengarah ke browser yang paling kompatibel dan bukti masa depan (karena masalah ini pada akhirnya akan menjadi standar) jawaban untuk pertanyaan Anda:

J: fragmen dari URL asli dibuang.

B: fragmen dari Locationheader dihormati.

kapak.
sumber
1
Saya lupa tentang beberapa aturan "penulisan ulang" yang saya tetapkan di server HTTP, yang mungkin diterapkan sebagai pengalihan 301. Akibatnya, IE terus kehilangan pengenal fragmen karena saat Anda memiliki beberapa pengalihan, fragmen yang disetel oleh pengalihan pertama menjadi bagian dari URI sumber di urutan kedua.
Eugene Yokota
opera 12.12 menghormati fragmen di header lokasi saat ada.
kambing
4
Pada versi Chrome dan Firefox saat ini: A tidak benar. Pada versi Firefox saat ini: B tidak benar. Saat ini, jika Anda harus menggunakan hashes (misalnya, menggunakan perutean Backbone) tampaknya pengalihan berbasis javascript adalah satu-satunya pilihan Anda yang sebenarnya.
a.real.human.being
Blok yang dikutip tampaknya bertentangan dengan dirinya sendiri. Pertama dikatakan "IE (8) mengabaikan fragmen di URI lokasi, sehingga akan menggunakan fragmen dari URI sumber, saat ada", kemudian muncul tulisan "Tampaknya IE8 memang menggunakan pengenal fragmen dari Lokasi". Apakah yang pertama mengacu pada sesuatu yang berbeda dari yang kedua?
davidtbernal
B tidak benar untuk Chome 45.0.2454.85. B benar untuk Firefox 40.0.3.
Jingguo Yao
44

Safari 5 dan IE9 dan di bawahnya melepaskan fragmen URI asli jika pengalihan HTTP / 3xx terjadi. Jika header Lokasi pada respons menentukan fragmen, itu akan digunakan.

IE10 +, Chrome 11+, Firefox 4+, dan Opera semua akan "memasang kembali" fragmen URI asli setelah mengikuti pengalihan 3xx.

Halaman pengujian: http://www.webdbg.com/test/redir/fragment/ .

Lihat diskusi lebih lanjut tentang masalah ini di http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx

EricLaw
sumber
2
Sebenarnya IE10 masih berperilaku berbeda dari versi Firefox dan Chrome terbaru. Tampaknya mempertahankan fragmen dari URL sumber jika terjadi pengalihan sederhana. Dan jika pengalihan Locationberisi fragmen, itu akan menyimpannya dengan benar. Namun jika pengalihan Locationdengan fragmen melewati pengalihan 3xx lainnya, secara misterius ia akan mengabaikan fragmen dari pengalihan pertama, yang tidak konsisten dengan 2 perilaku sebelumnya. Chrome dan Firefox secara konsisten melestarikannya.
Odony
Saya telah memastikan bahwa Anda benar. Lihat tautan tes terakhir di halaman ini: webdbg.com/test/redir/fragment
EricLaw
11

Sekadar memberi tahu Anda, di sini Anda dapat menemukan spesifikasi yang tepat. dengan w3c mendefinisikan bagaimana semua harus berperilaku: http://www.w3.org/TR/cuap#uri - klausul 4.1 - lihat di bawah:

Saat sumber daya (URI1) telah dipindahkan, pengalihan HTTP dapat menunjukkan lokasi barunya (URI2).

Jika URI1 memiliki pengenal fragmen #frag, target baru yang harus coba dijangkau oleh agen pengguna adalah URI2 # frag. Jika URI2 sudah memiliki pengenal fragmen, #frag tidak boleh ditambahkan dan target barunya adalah URI2.

Salah: Sebagian besar agen pengguna saat ini menerapkan pengalihan HTTP tetapi tidak menambahkan pengenal fragmen ke URI baru, yang umumnya membingungkan pengguna karena mereka berakhir dengan sumber daya yang salah.

Referensi:

Pengalihan HTTP dijelaskan di bagian 10.3 dari spesifikasi HTTP / 1.1 [RFC2616]. Perilaku yang diperlukan dijelaskan secara mendetail di "Penanganan pengidentifikasi fragmen di URL yang dialihkan" [RURL]. Istilah "Persistent Uniform Resource Locator (PURL)" menunjukkan URL (kasus khusus URI) yang mengarah ke URL lain melalui pengalihan HTTP. Untuk informasi lebih lanjut, lihat "Persistent Uniform Resource Locators" [PURL]. Contoh:

Misalkan pengguna meminta sumber daya di http://www.w3.org/TR/WD-ruby/#changes dan server mengalihkan agen pengguna ke http://www.w3.org/TR/ruby/ . Sebelum mengambil URI terakhir itu, browser harus menambahkan pengenal fragmen #changes padanya: http://www.w3.org/TR/ruby/#changes .

Marcin
sumber
0

Posting masalah serupa dengan solusi yang saya hadapi.

Semoga dapat membantu seseorang dengan persyaratan serupa preserving hash in IEuntuk 302 pengalihan.

Menambahkan bagian penting dari jawaban alih-alih tautan saja

Kami menggunakan SiteMinderotentikasi dalam aplikasi kami.

Saya menemukan bahwa setelah otentikasi berhasil, SiteMinderlakukan 302 redirectionke halaman aplikasi yang diminta pengguna dengan menggunakan variabel tersembunyi formulir loginvalue (di mana ia menyimpan URL yang diminta pengguna /myapp/- without hash fragmentkarena tidak akan dikirim ke server) dengan nama yang mirip dengan redirect. Contoh formulir di bawah ini

Contoh formulir login

Karena nilairedirect variabel tersembunyi hanya berisi tanpa fragmen hash dan ini adalah pengalihan 302, fragmen hash secara otomatis dihapus oleh IE bahkan sebelum masuk ke aplikasi kami dan solusi apa pun yang kami coba dalam kode aplikasi kami tidak berhasil./myapp/

IE hanya mengalihkan /myapp/dan mendarat di halaman beranda default aplikasi kami https://ourapp.com/myapp/#/home.

Telah menyia-nyiakan waktu hampir sehari untuk mencari tahu perilaku ini.

Solusinya adalah:

Telah mengubah form login variabel tersembunyi ( redirect) nilai untuk memegang fragmen hash dengan menambahkan window.location.hashbersama dengan nilai yang ada. Mirip dengan kode di bawah ini

$(function () {
  var $redirect = $('input[name="redirect"]');
  $redirect.val($redirect.val() + window.location.hash);
});

Setelah perubahan ini, redirectvariabel tersembunyi menyimpan nilai URL yang diminta pengguna sebagai /myapp/#/pending/requestsdan SiteMindermengarahkannya ke /myapp/#/pending/requestsIE.

Solusi di atas berfungsi dengan baik di ketiga browser Chrome, Firefox and IE.

Terima kasih kepada @AlexFord untuk penjelasan mendetail dan memberikan solusi untuk masalah ini.

Prathap Reddy
sumber