Як запобігти кешування сторінки браузера в Rails


151

Ubuntu -> Apache -> Phusion Passenger -> Rails 2.3

Основна частина мого сайту реагує на ваші кліки. Таким чином, якщо ви натиснете на посилання, воно надішле вас до місця призначення та негайно відновить вашу сторінку.

Але якщо натиснути кнопку назад, ви не побачите нової сторінки. На жаль, це не відображається без оновлення вручну; видається, що браузер кешує його. Хочу переконатися, що браузер не кешує сторінку.

Окремо я б хочу встановити дати закінчення терміну дії далеко в майбутньому для всіх моїх статичних активів.

Який найкращий спосіб вирішити це? Чи варто це вирішити в Rails? Апач? Javascript?

Дякую за всю вашу допомогу, Джейсоне


На жаль Жодна з цих пропозицій не змусила поведінку, яку я шукаю.

Можливо, є відповідь на javascript? Я міг би з рейок виписати позначку в коментарі, а потім перевірити javascript, щоб перевірити, чи час у межах п'яти секунд (або що працює). Якщо так, то добре, але якщо ні, то перезавантажити сторінку?

Як ви думаєте, це спрацювало б?

Дякуємо за всю вашу допомогу,

Джейсон

Відповіді:


335

Нарешті з’ясував це - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/ вapplication_controller.rb

Після рейки 5:

class ApplicationController < ActionController::Base

  before_action :set_cache_headers

  private

  def set_cache_headers
    response.headers["Cache-Control"] = "no-cache, no-store"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"
  end
end

Рейки 4 та старіші версії:

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"] = "Mon, 01 Jan 1990 00:00:00 GMT"
  end
end

3
Чи слід це загорнути в "if request.xhr?" тож він встановлюється лише на оновлення ajax, але нормальні сторінки не так?
MintDeparture

3
Вам дійсно потрібно лише до Cache-Control: no-storeтих пір, поки браузер сумісний із HTTP 1.1. Розділ 14.9.2 Що може зберігатися
кешами

28
1 січня 1990 року був понеділок!
Ян Геттіч

2
Це не працює для мене, я додав той самий код у application_controller.rb і після виходу я можу побачити останню сторінку кнопкою "назад". Підкажіть, будь ласка, куди я помиляюся?
Торін

1
Чи це також НЕ кешувати JS та CSS у додатку rails? Чи завантажуватимуться JS та CSS з сервера для кожного запиту?
furiabhavesh

14

3
expires_nowнадсилає лише no-cacheзаголовок. Залежно від браузера цього може бути недостатньо. (Наприклад, Firefox хоче підключення no-storeдля не-HTTPS: developer.mozilla.org/uk/docs/Using_Firefox_1.5_caching )
Даніель Риковський

1
Погоджено, це не є дійсним рішенням, тестування на Rails 5.2 та Chrome 77. no-storeтакож потрібно.
AndrewSouthpaw

3

Я використовував цей рядок з певним успіхом у контролері. Він працює в Safari та Internet Explorer, але я не бачив, щоб він працював з Firefox.

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

Для другого моменту, якщо ви використовуєте подібні методи рейки

stylesheet_link_tag

і залиште налаштування за замовчуванням на своєму веб-сервері, активи зазвичай кешуються досить добре.


3
1.year.agoзайва накладні витрати. Просто виберіть якийсь довільний час у минулому, наприкладFri, 01 Jan 1990 00:00:00 GMT
Архонічний

6
@Archonic 1 січня 1990 року був понеділок!
Томас Р. Колл

1

Чистішим способом було б написати проміжне програмне забезпечення Rack, яке змінює заголовок Cache-Control на основі певної логіки (наприклад, лише для mime-типу application / xml). Або для більш химерного, але все ще працюючого підходу можна змінити константу ActionDispatch :: Response :: DEFAULT_CACHE_CONTROL на 'no-cache'. Звичайно, якщо потрібна деталізація контролера та / або дії, то краще зробити це в контролері.


1

Зауваження: Ви не можете умовно очистити кеш-пам'ять (наприклад, якщо a before_filterтільки дзвонить, reset_cacheякщо користувач уже там був). Вам потрібно беззастережно очистити кеш-пам'ять, оскільки браузер не зробить новий запит, щоб побачити, чи цього разу його потрібно перезавантажити, хоча він не потребував останній раз.

Приклад:

before_filter :reset_cache, if: :user_completed_demographics?

не допоможе запобігти поверненню користувачів після того, як вони були там, оскільки браузер використовує оригінальні заголовки кешу на кнопці Назад.

before_filter :reset_cache

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


0

no_cache_control Самоцвіт.

Якщо вам потрібно зробити це для всіх відповідей, наприклад, пройти тест на проникнення (BURP, Detectify тощо), ви можете встановити цей Gem на Rails 4+ для того, щоб додати наступні заголовки до всіх відповідей:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: -1

Це як шарм, і це справді правильний шлях для безпечних веб-додатків HTTPS, для виконання яких потрібна автентифікація.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.