Фрагмент URL-адреси та 302 переадресації


136

Добре відомо, що фрагмент URL-адреси (частина після #) не надсилається серверу.

Мені цікаво, як працюють фрагменти під час переадресації сервера (через статус HTTP 302 та Location:заголовка).

Моє запитання справді двояке:

  1. Якщо в оригінальній URL-адресі був фрагмент ( /original.php#foo), і перенаправлення робиться на /new.php, чи фрагментарна частина вихідної URL-адреси просто втрачається? Або іноді він застосовується до нової URL-адреси?
    Чи буде нова URL-адреса коли-небудь /new.php#fooу цьому випадку?

  2. Незалежно від оригінальної URL-адреси, якщо сервер перенаправить на нову URL-адресу з фрагментом ( /new.php#foo), чи отримає фрагмент "честь"? Або справді сервер взагалі не має жодних діл, що втручаються у фрагмент - і, таким чином, браузер ігнорує його, просто перейшовши /new.php??


1
Тут ви можете знайти специфікацію за W3C: w3.org/TR/cuap#uri п. 4.1. фрагмент слід зберегти на переадресацію.
Марцін

Відповіді:


135

Оновлення 2014 - 27 червня :

RFC 7231, протокол передачі гіпертексту (HTTP / 1.1): семантика та вміст , опублікований як ПРОПОЗИЦІЙНА СТАНДАРТА. Із журналу змін :

Синтаксис поля заголовка Location було змінено, щоб дозволити всі посилання URI, включаючи відносні посилання та фрагменти, а також деякі пояснення щодо того, коли використання фрагментів було б недоцільним. (Розділ 7.1.2)

Важливі моменти розділу 7.1.2. Розташування :

Якщо значення Location, надане у відповіді 3xx (перенаправлення), не має компонента фрагмента, агент користувача ОБОВ'ЯЗКОВО обробляє перенаправлення так, як якщо б значення успадковувало компонент фрагмента посилання URI, що використовується для генерування цілі запиту (тобто перенаправлення успадковується оригінальний фрагмент посилання, якщо такий є).

Наприклад, запит GET, згенерований для URI-посилання " http://www.example.org/~tim ", може призвести до відповіді 303 (див. Інше), що містить поле заголовка:

Location: /People.html#tim

що говорить про те, що агент користувача перенаправляє на " http://www.example.org/People.html#tim "

Аналогічно, запит GET, згенерований для посилання URI " http://www.example.org/index.html#larry ", може призвести до відповіді 301 (постійно переміщеної), що містить поле заголовка:

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

що говорить про те, що агент користувача перенаправляє на " http://www.example.net/index.html#larry ", зберігаючи оригінальний ідентифікатор фрагмента.

Це має чітко відповісти на ваші запитання.

Оновити END

це відкрита (не вказана) проблема з поточною специфікацією HTTP . Він розглядається в двох випусках робочої групи IETF httpbis :

№6 дозволяє фрагменти в Locationзаголовку. # 43 говорить про це:

Я просто тестував це за допомогою різних браузерів.

  • Firefox і Safari використовують фрагмент у заголовку місцезнаходження.
  • Opera використовує фрагмент з URI-джерела, коли він присутній, інакше фрагмент з місця переадресації
  • IE (8) ігнорує фрагмент у URI розташування, таким чином, використовує фрагмент з вихідного URI, коли він присутній

Пропозиція:

"Примітка. Поведінка, коли ідентифікатори фрагментів від початкового URI та перенаправлення потрібно поєднувати, не визначені; поточні Агенти користувача дійсно відрізняються від того, який фрагмент має перевагу."

[...]

Виявляється , що IE8 робить використання фрагмента idenfitier з Location(поведінку я бачив , може бути обмежена локального хоста).

Таким чином, нам здається, що ми маємо послідовну поведінку для Safari / IE / Firefox / Chrome (щойно перевірене), оскільки фрагмент із заголовка Location використовується, незважаючи на те, яким був початковий URI.

Тому я змінюю свою пропозицію задокументувати це як очікувану поведінку.

це призводить до найбільш сумісного з веб-переглядачами та майбутнього підтвердження (оскільки ця проблема згодом отримає стандартизовану відповідь) на ваше питання:

A: фрагменти з оригінальних URL-адрес видаляються.

Б: фрагменти із Locationзаголовка вшановуються.


1
Я забув про деякі правила "переписати", які я встановив на серверах HTTP, які, ймовірно, реалізовані як переадресація 301. Як наслідок, IE продовжував втрачати ідентифікатор фрагмента, оскільки, коли у вас є декілька переадресацій, фрагменти, встановлені першим переадресацією, стають частиною URI джерела у другому.
Євген Йокота

Opera 12.12 вшановує фрагмент у заголовку місцеположення, коли він присутній.
коза

4
У поточних версіях Chrome і Firefox: A це неправда. У поточній версії Firefox: B не відповідає дійсності. На даний момент, якщо вам доведеться використовувати хеші (наприклад, за допомогою маршрутизації Backbone), здається, що перенаправлення на основі Javascript - ваш єдиний реальний варіант.
a.real.human.being

Цитується блок, здається, суперечить сам собі. Спочатку йдеться про те, що "IE (8) ігнорує фрагмент у URI розташування, таким чином, використовує фрагмент з вихідного URI, коли він присутній", потім пізніше він каже "Схоже, що IE8 використовує ідентифікатор фрагмента з Location". Чи перше посилається на щось відмінне від другого?
davidtbernal

B не вірно для Chome 45.0.2454.85. B вірно для Firefox 40.0.3.
Jingguo Yao

44

Safari 5 і IE9 і нижче скидають оригінальний фрагмент URI, якщо відбувається перенаправлення HTTP / 3xx. Якщо заголовок Location у відповіді вказує фрагмент, він використовується.

IE10 +, Chrome 11+, Firefox 4+ та Opera усі "повторно приєднають" оригінальний фрагмент URI після перенаправлення 3xx.

Тестова сторінка: http://www.webdbg.com/test/redir/fragment/ .

Дивіться подальше обговорення цього питання на веб-сторінці http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx


2
Насправді IE10 все ще поводиться інакше, ніж останні версії Firefox та Chrome. Здається, зберігається фрагмент від вихідної URL-адреси у випадку простого переспрямування. І якщо переспрямування Locationмістить фрагмент, він буде зберігати його правильно. Але якщо перенаправлення Locationз фрагментом пройде через інше перенаправлення 3xx, воно незрозуміло ігнорує фрагмент з першого перенаправлення, що не відповідає двом попереднім поведінкам. Chrome і Firefox послідовно зберігають його.
odony

Я підтвердив, що ти прав. Дивіться останнє тестове посилання на цій сторінці: webdbg.com/test/redir/fragment
EricLaw

11

Просто для того, щоб повідомити, тут ви можете знайти належні характеристики. w3c, визначаючи, як слід поводитись: http://www.w3.org/TR/cuap#uri - п. 4.1 - див. нижче:

Коли ресурс (URI1) перемістився, перенаправлення HTTP може вказати на його нове місце (URI2).

Якщо URI1 має ідентифікатор фрагмента #frag, то новою ціллю, яку повинен намагатися досягти агент користувача, буде URI2 # frag. Якщо URI2 вже має ідентифікатор фрагмента, то #frag не слід додавати, а нова ціль - URI2.

Неправильно: Більшість поточних користувальницьких агентів реалізують перенаправлення HTTP, але не додають ідентифікатор фрагмента до нового URI, що, як правило, збиває з пантелику користувача, оскільки в кінцевому підсумку він не відповідає ресурсу.

Список літератури:

Перенаправлення HTTP описані в розділі 10.3 специфікації HTTP / 1.1 [RFC2616]. Необхідна поведінка докладно описана в "Обробці ідентифікаторів фрагментів у перенаправлених URL-адресах" [RURL]. Термін "Постійний рівномірний локатор ресурсів (PURL)" позначає URL (особливий випадок URI), який вказує на інший через перенаправлення HTTP. Для отримання додаткової інформації див. "Постійні уніфіковані локатори ресурсів" [PURL]. Приклад:

Припустимо, користувач запитує ресурс за адресою http://www.w3.org/TR/WD-ruby/#changes, а сервер перенаправляє агент користувача на http://www.w3.org/TR/ruby/ . Перед тим, як отримати останній URI, браузер повинен додати до нього ідентифікатор фрагмента # Changes: http://www.w3.org/TR/ruby/#changes .


0

Опублікував подібну проблему із вирішенням, яке зі мною стоїть.

Сподіваємось, це допомагає комусь із подібною вимогою preserving hash in IEдо 302 переадресацій.

Додавання істотних частин відповіді замість посилань

Ми використовуємо SiteMinderавтентифікацію в нашій програмі.

Я зрозумів, що після успішної автентифікації SiteMinderце робить 302 redirectionдля запитуваної користувачем сторінки програми, використовуючи приховану змінну форми входуvalue (де вона зберігає запитуваний користувачем URL /myapp/- without hash fragmentоскільки він не буде відправлений на сервер) з ім'ям, подібним до redirect. Зразок форми нижче

Зразок форми для входу

Оскільки redirectприховане змінне значення містить лише /myapp/без хеш-фрагменту, і це перенаправлення 302, хеш-фрагмент автоматично видаляється IE ще до того, як прийти до нашої програми, і будь-які рішення, які ми намагаємося в нашому коді програми, не розробляються.

IE переспрямовується на /myapp/лише, і він знаходиться на домашній сторінці за замовчуванням нашого додатка https://ourapp.com/myapp/#/home.

Ви витратили майже день, щоб з'ясувати таку поведінку.

Рішення таке:

Змінили форму Ввійти прихованої змінної ( redirect) значення для зберігання хеш - фрагмент, докладаючи window.location.hashразом з існуючим значенням. Схожий на код нижче

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

Після цієї зміни redirectприхована змінна зберігає запитане користувачем значення URL як /myapp/#/pending/requestsі SiteMinderперенаправляє його /myapp/#/pending/requestsв IE.

Вищевказане рішення працює чудово у всіх трьох браузерах Chrome, Firefox and IE.

Дякуємо @AlexFord за детальне пояснення та надання вирішення цього питання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.