Как предотвратить кеширование страниц браузера в Rails

138

Ubuntu → Apache → Phusion Passenger → Rails 2.3

Основная часть моего сайта реагирует на ваши клики. Итак, если вы нажмете на ссылку, она отправит вас в пункт назначения и мгновенно восстановит вашу страницу.

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

Отдельно, я хочу установить даты истечения дат будущего для всех моих статических активов.

Какой лучший способ решить эту проблему? Должен ли я решить это в Rails? Apache? Javascript?

Спасибо за вашу помощь, Джейсон


Увы. Ни одно из этих предложений не привело к поведению, которое я ищу.

Может быть, есть ответ на javascript? Я мог бы, чтобы рельсы записывали временную метку в комментарии, а затем проверили javascript, чтобы проверить, не осталось ли времени в течение пяти секунд (или что-то работает). Если да, то хорошо, но если нет, то перезагрузите страницу?

Считаете ли вы, что это сработает?

Спасибо за вашу помощь,

Джейсон

Теги:
http-headers
caching

5 ответов

320
Лучший ответ

Наконец понял это - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/ в application_controller.rb

class ApplicationController < ActionController::Base

before_filter :set_cache_headers

  private

  def set_cache_headers
    response.headers["Cache-Control"] = "no-cache, no-store"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
  end
end
  • 3
    Должно ли это быть заключено в "if request.xhr?" поэтому он устанавливается только при обновлении ajax, а обычные страницы - нет?
  • 0
    @Smickie Я сделал именно это. Мне нужно было только, чтобы мои Ajax-запросы не кэшировались. В противном случае этот ответ идеально подходит!
Показать ещё 7 комментариев
14

использование:

expires_now()

http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-expires_now

  • 2
    Это не сработало для меня в Chrome 21.0.1180.57.
  • 1
    expires_now отправляет только заголовок no-cache . В зависимости от браузера этого может быть недостаточно. (Например, Firefox хочет, чтобы no-store не было подключений, отличных от HTTPS: developer.mozilla.org/en/docs/Using_Firefox_1.5_caching )
Показать ещё 1 комментарий
3

Я использовал эту строку с некоторым успехом в контроллере. Он работает в Safari и Internet Explorer, но я не видел, чтобы он работал с Firefox.

response.headers["Expires"] = "#{1.year.ago}"

Для вашего второго пункта, если вы используете вспомогательные методы rails, например

stylesheet_link_tag

и оставьте настройки по умолчанию на вашем веб-сервере, активы обычно кэшируются довольно хорошо.

  • 3
    1.year.ago это ненужные накладные расходы. Просто выберите произвольное время в прошлом, например, Fri, 01 Jan 1990 00:00:00 GMT
  • 2
    @ Archonic 1 января 1990 был понедельник!
1

Более чистым способом было бы написать промежуточное ПО Rack, которое изменяет заголовок Cache-Control на основе некоторой логики (например, только для application/xml mime-type). Или, для более уродливого, но все еще работающего подхода, можно изменить константу ActionDispatch:: Response:: DEFAULT_CACHE_CONTROL на "no-cache". Конечно, если требуется размерность контроллера и/или действия, тогда лучше сделать это в контроллере.

0

Примечание. Вы не можете условно очистить кеш (например, если before_filter вызывает только reset_cache, если пользователь уже был там). Вам необходимо безоговорочно очистить кеш, потому что браузер не будет делать новый запрос, чтобы увидеть, на этот раз он должен перезагрузиться, даже если это не нужно в последний раз.

Пример:

before_filter :reset_cache, if: :user_completed_demographics?

не будет работать, чтобы пользователи не возвращались после того, как они были там, поскольку браузер использует исходные заголовки кеша на кнопке "Назад".

before_filter :reset_cache

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню