Фрагмент URL и 302 редиректа

Хорошо известно, что фрагмент 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 ??


person levik    schedule 18.02.2010    source источник
comment
Здесь вы можете найти спецификацию W3C: пункт w3.org/TR/cuap#uri 4.1. фрагмент должен быть сохранен при перенаправлении.   -  person Marcin    schedule 01.07.2012


Ответы (4)


Обновление, 27 июня 2014 г.:

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. он рассматривается в двух выпусках http://www.ietf.org/dyn/wg/charter/httpbis-charter.html:

# 6 разрешает фрагменты в заголовке Location. # 43 говорит это:

Я только что протестировал это в разных браузерах.

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

Предложение:

«Примечание: поведение при объединении идентификаторов фрагментов из исходного URI и перенаправления не определено; текущие пользовательские агенты действительно различаются в зависимости от того, какой фрагмент имеет приоритет».

[...]

Похоже, что IE8 действительно использует идентификатор фрагмента из Location (поведение, которое я видел, может быть ограничено localhost).

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

Поэтому я изменяю свое предложение, чтобы задокументировать это как ожидаемое поведение.

это приводит к наиболее совместимому с браузером и перспективному (потому что эта проблема со временем станет стандартизированным) ответом на ваш вопрос:

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

B: фрагменты из заголовка Location учитываются.

person ax.    schedule 21.02.2010
comment
Я забыл о некоторых правилах перезаписи, которые я установил на HTTP-серверах, которые, вероятно, были реализованы как перенаправление 301. Как следствие IE продолжал терять идентификатор фрагмента, потому что, когда у вас есть несколько перенаправлений, фрагменты, установленные первым перенаправлением, становятся частью URI source во втором. - person Eugene Yokota; 09.04.2011
comment
Opera 12.12 учитывает фрагмент в заголовке местоположения, если он присутствует. - person goat; 29.12.2012
comment
В текущих версиях Chrome и Firefox: A неверно. В текущей версии Firefox: B неверно. На данный момент, если вам нужно использовать хэши (например, используя маршрутизацию Backbone), кажется, что перенаправление на основе javascript - ваш единственный реальный вариант. - person a.real.human.being; 10.11.2013
comment
Цитируемый блок кажется противоречащим самому себе. Сначала он говорит, что IE (8) игнорирует фрагмент в URI местоположения, таким образом, будет использовать фрагмент из исходного URI, если он присутствует, затем позже он говорит, что IE8 действительно использует идентификатор фрагмента из Location. Первое относится к чему-то отличному от второго? - person davidtbernal; 27.06.2014
comment
B неверно для Chome 45.0.2454.85. B верно для Firefox 40.0.3. - person Jingguo Yao; 12.09.2015

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

person EricLaw    schedule 06.05.2011
comment
На самом деле IE10 по-прежнему ведет себя иначе, чем последние версии Firefox и Chrome. Кажется, что он сохраняет фрагмент исходного URL-адреса в случае простого перенаправления. И если перенаправление Location содержит фрагмент, оно сохранит его правильно. Но если перенаправленный Location с фрагментом проходит через другое перенаправление 3xx, он необъяснимым образом проигнорирует фрагмент из первого перенаправления, что не согласуется с двумя предыдущими вариантами поведения. Chrome и Firefox постоянно его сохраняют. - person odony; 19.11.2013
comment
Я подтвердил, что вы правы. См. Последнюю ссылку на тест на этой странице: webdbg.com/test/redir/fragment - person EricLaw; 20.11.2013

Просто чтобы вы знали, здесь вы можете найти подходящую спецификацию. от 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), который указывает на другой URL-адрес посредством перенаправления 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.

person Marcin    schedule 01.07.2012

Публикация аналогичной проблемы с решением, с которой я столкнулся.

Надеюсь, это поможет кому-то с аналогичным требованием preserving hash in IE для переадресации 302.

Добавление основных частей ответа вместо одних ссылок

В нашем приложении мы используем SiteMinder аутентификацию.

Я выяснил, что после успешной аутентификации SiteMinder выполняет 302 redirection на странице приложения, запрошенной пользователем, используя скрытую переменную формы входа value (где хранится запрошенный пользователем URL-адрес /myapp/ - without hash fragment, поскольку он не будет отправлен на server) с именем, похожим на 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 за подробное объяснение и предоставление решение этой проблемы.

person Prathap Reddy    schedule 15.07.2020