Фрагмент URL и 302 перенаправления

136

Хорошо известно, что фрагмент URL (часть после #) не отправляется на сервер.

Мне, правда, интересно, как работают фрагменты, когда Location:задействовано перенаправление сервера (через HTTP-статус 302 и заголовок).

Мой вопрос действительно двоякий:

  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-Jun-27 :

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

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

Важные моменты из Раздела 7.1.2. Расположение :

Если значение Location, указанное в ответе 3xx (Redirection), не имеет компонента фрагмента, пользовательский агент ДОЛЖЕН обработать перенаправление, как если бы значение наследовало компонент фрагмента ссылки 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 from Location(поведение, которое я видел, может быть ограничено localhost).

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

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

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

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

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

Топор.
источник
1
Я забыл о некоторых «правилах перезаписи», которые я установил на HTTP-серверах, которые, вероятно, были реализованы как редирект 301. Как следствие, IE продолжал терять идентификатор фрагмента, потому что, когда у вас есть несколько перенаправлений, фрагменты, установленные первым перенаправлением, становятся частью исходного URI во втором.
Юджин Йокота
опера 12.12 учитывает фрагмент в заголовке местоположения, когда присутствует.
коза
4
На текущих версиях Chrome и Firefox: A не соответствует действительности. На текущей версии Firefox: B не соответствует действительности. На данный момент, если вам нужно использовать хэши (например, с использованием маршрутизации Backbone), кажется, что перенаправление на основе javascript - ваш единственный реальный вариант.
a.real.human.being
Цитируемый блок, кажется, противоречит сам себе. Сначала он говорит: «IE (8) игнорирует фрагмент в URI местоположения, поэтому будет использовать фрагмент из исходного URI, когда он присутствует», затем позже он говорит «Похоже, что IE8 действительно использует идентификатор фрагмента из Location». Первое относится к чему-то отличному от второго?
Давидтбернал
B не верно для Chome 45.0.2454.85. B верно для Firefox 40.0.3.
Цзинго Яо
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.

EricLaw
источник
2
На самом деле IE10 по-прежнему ведет себя не так, как в последних версиях Firefox и Chrome. Похоже, что он сохраняет фрагмент из исходного URL в случае простого перенаправления. И если редирект Locationсодержит фрагмент, он сохранит его правильно. Но если перенаправление Locationс фрагментом проходит через перенаправление 3xx, он необъяснимым образом проигнорирует фрагмент из первого перенаправления, что не согласуется с 2 предыдущими поведениями. Chrome и Firefox последовательно сохраняют его.
Одони
Я подтвердил, что ты прав. Смотрите последнюю ссылку для тестирования на этой странице: 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 .

Marcin
источник
0

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

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

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

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

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

Пример формы входа

Поскольку значениеredirect скрытой переменной содержит только фрагмент без хэша и это перенаправление 302, этот фрагмент хэша автоматически удаляется IE даже до того, как он попадает в наше приложение, и какие бы решения мы ни пытались применить в коде нашего приложения, они не работают./myapp/

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 за подробное объяснение и решение этой проблемы.

Пратхап Редди
источник