Согласование содержимого игнорируется при использовании кнопки «Назад» в браузере

Вот ситуация:

У меня есть веб-приложение, которое отвечает на запрос списка ресурсов, скажем:

/items

Первоначально это запрашивается непосредственно веб-браузером при переходе по этому пути. Браузер использует стандартный заголовок «Принять», который включает «текст/html», и мое приложение замечает это и возвращает содержимое HTML для списка элементов.

В возвращенном HTML есть некоторый JavaScript (jQuery), который затем выполняет запрос ajax для получения фактических данных:

/items

Только на этот раз заголовок «Accept» явно установлен на «application/json». Опять же, мое приложение это замечает и в запрос корректно возвращается JSON, данные вставляются в страницу, и все устраивает.

Вот и возникает проблема: пользователь переходит на другую страницу, а затем нажимает кнопку НАЗАД. Затем им будет предложено сохранить файл. Оказывается, это данные JSON списка элементов.

До сих пор я подтверждал, что это происходит как в Google Chrome, так и в Firefox 3.5.

Здесь возможны два типа ответов:

  1. Как я могу исправить проблему. Есть ли какая-то волшебная комбинация заголовков Cache-Control или другое колдовство, которое заставляет браузер делать правильные вещи здесь?

  2. Если вы думаете, что я делаю что-то ужасно неправильное, что мне делать? Я ищу правильность, но также стараюсь не жертвовать гибкостью.

Если это поможет, приложение представляет собой веб-приложение JAX-RS, использующее Restlet 2.0m4. Я могу предоставить образцы заголовков запроса/ответа, если это полезно, но я считаю, что проблема полностью воспроизводима.


person Mark Renouf    schedule 23.09.2009    source источник
comment
Это похоже на будущую проблему, с которой я столкнусь после того, как выясню (stackoverflow.com/questions/5250923). Мне любопытно, вы в конечном итоге придерживаетесь этого решения или в конечном итоге отказались от него для других URL-адресов? Чистота единого URL-адреса RESTful для разных представлений одного и того же ресурса, безусловно, идеальна.   -  person mckamey    schedule 09.03.2011


Ответы (3)


Есть ли какая-то волшебная комбинация заголовков Cache-Control или другое колдовство, которое заставляет браузер делать правильные вещи здесь?

Если вы отправляете разные ответы на разные заголовки Accept:, вы должны включить заголовок:

Vary: Accept

в вашем ответе. Заголовок Vary также должен содержать любые другие заголовки запроса, которые влияют на ответ, поэтому, например, если вы выполняете сжатие gzip/deflate, вам нужно будет включить Accept-Encoding.

IE, к сожалению, плохо обрабатывает многие значения Vary, полностью нарушая кеширование, что может иметь для вас значение, а может и не иметь.

Если вы думаете, что я делаю что-то ужасно неправильное, что мне делать?

Я не думаю, что идея предоставления разного контента для разных типов по одному и тому же URL-адресу ужасно неверна, но вы допускаете больше проблем с совместимостью, чем вам действительно нужно. На практике полагаться на заголовки, работающие через JSON, не очень хорошая идея; лучше всего использовать другой URL, например /items/json или /items?format=json.

person bobince    schedule 23.09.2009
comment
Обслуживание другого ресурса по тому же URL-адресу является неправильным; обслуживание различных представлений одного и того же ресурса - это то, что должен делать HTTP. Вы хотите увидеть его в формате XML, JSON, красиво отформатированном читаемом HTML или в виде обычного текста? Это всегда одно и то же, но с вашим выбором форматов. К сожалению, некоторые браузеры нарушают это, и вам приходится использовать хак, как в ответе. Если ваш сервис предлагает как application/json, так и text/html, Internet Explorer выберет версию JSON из-за своего странного заголовка Accept. - person Mark Lutton; 29.10.2009

Я знаю, что этот вопрос старый, но на всякий случай кто-нибудь еще столкнется с этим:

У меня была такая же проблема с приложением Rails с использованием jQuery, и я исправил ее, сказав браузеру не кэшировать ответ JSON с приведенным здесь решением для другого вопроса:

jQuery $.getJSON работает только один раз для каждого элемента управления. Не достигает сервера снова

Проблема возникла только с Chrome и Firefox. Safari нормально обрабатывал обратное поведение без явного указания не кэшировать.

person bobfet1    schedule 17.05.2011
comment
Этот ответ сработал для меня, если вы установите для параметра кеша в своем запросе jQuery.ajax() значение false, вы можете нанести ответный удар, и он будет работать, как ожидалось. - person Scott Harvey; 08.09.2011

Старый вопрос, но для всех, кто это видит, нет ничего плохого в том, что спрашивающий использует заголовок Accept.

Это подтвержденная ошибка в Chrome. (Ранее также в Firefox, но с тех пор исправлено.)

http://code.google.com/p/chromium/issues/detail?id=94369

person Tom Christie    schedule 24.10.2012