Кнопка "Назад" (Chrome) Получает Json вместо HTML в Play Framework

Folks,  У меня есть веб-приложение, в котором я повторно использовал один и тот же маршрут для JSON и HTML-представлений одного и того же ресурса, позвольте называть его /foo/details на данный момент. Эта страница связана, откройте ее /bar/details. (так что, глядя на /bar/details вы видите ссылку на → /foo/details).

Когда я перехожу с первой страницы на вторую, все работает нормально. Когда я нажимаю кнопку "Назад" в Chrome, исходная страница отображается как JSON вместо HTML. Если я ударил обновление в браузере, я получаю представление HTML, а не JSON.

Вот код, который я использую для обнаружения JSON vs HTML:

res.result.map { group =>
  render {
    case Accepts.Html() => Ok(views.html.groups.details(group))
    case Accepts.Json() => Ok(Json.toJson(group))
  }
}.getOrElse(NotFound)

Это стандартная реализация этого шаблона, и он работает повсюду, за исключением случаев, когда я использую кнопку "Назад" в Chrome в определенных ситуациях.

Есть ли какое-то значение, которое я не очищаю, или что-то, что мои страницы делают с Ajax, который запутывает Play, чтобы сделать его рендерингом в Json, или, возможно, Chrome кэширует страницу, но кэширует неправильный заголовок accepts

Я могу обойти это, используя два разных маршрута: один для Json и один для Html, но мне это не нравится, поскольку мне кажется, что я сдаюсь.

У кого-нибудь есть идеи относительно того, что вызывает это поведение только в обратной кнопке?

Ответ 1

Это был кеш браузера Chrome. Он не делает различий между запросом, сделанным в /foo/bar, с помощью "Accept" → "application/json" и с обычным заголовком HTML-принятия. В результате я бы загрузил HTML-страницу, JavaScript на этой странице попал бы в тот же URL-адрес для сырых данных JSON, а затем в следующий раз, когда я удалю, Chrome будет обслуживать кешированный JSON вместо кэшированного HTML.

В результате мне пришлось изменить маршруты, чтобы мой API JSON/REST прошел разные URL-адреса, чтобы Chrome (и Safari) не кэшировали JSON.

Ответ 2

Кевин, ты прав. Однако есть и другое решение.

Если вы добавите в заголовок ответа "Vary: Accept", это приведет к тому, что хром и другие браузеры с этой проблемой (например, Firefox v 21) будут различать кеш json и html. ПРИМЕЧАНИЕ. Vary: заголовок Accept-Encoding не работает, насколько я тестировал.

Если вы используете nginx, вы можете установить это: http://wiki.nginx.org/HttpProxyModule#proxy_set_header

proxy_set_header Vary Accept;

Однако существует проблема с nginx, где переменный заголовок accept не будет отправляться иногда, что-то делать с кешем. См. http://wiki.nginx.org/HttpProxyModule#proxy_set_header. Чтобы справиться с этим, вы можете включить gzip_vary для nginx, но это приведет к отправке заголовка Vary: Accept-Encoding. Этот заголовок не решает проблему.

Я использую рельсы, и я использовал файл before_filter, где я модифицировал response.headers["Vary"]= "Accept"

Я уверен, что есть другие способы сделать это с другими серверами/фреймворками.

Дополнительная информация: https://web.archive.org/web/20130114082345/http://blog.sdqali.in/blog/2012/11/27/on-rest-content-type-google-chrome-and-caching/