модуль ActionController::ConditionalGet
Открытые методы экземпляра
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 290
def expires_in(seconds, options = {})
response.cache_control.delete(:no_store)
response.cache_control.merge!(
max_age: seconds,
public: options.delete(:public),
must_revalidate: options.delete(:must_revalidate),
stale_while_revalidate: options.delete(:stale_while_revalidate),
stale_if_error: options.delete(:stale_if_error),
immutable: options.delete(:immutable),
)
options.delete(:private)
response.cache_control[:extras] = options.map { |k, v| "#{k}=#{v}" }
response.date = Time.now unless response.date?
end Устанавливает заголовок Cache-Control, перезаписывая существующие директивы. Этот метод также добавляет заголовок HTTP Date для совместимости с клиентами.
По умолчанию отправляется директива private, поэтому промежуточные кэши не должны кэшировать ответ.
Параметры
:public-
Если значение равно true, заменяет директиву
privateпо умолчанию директивойpublic. :must_revalidate-
Если значение равно true, добавляет директиву
must-revalidate. :stale_while_revalidate-
Задаёт значение директивы
stale-while-revalidate. :stale_if_error-
Задаёт значение директивы
stale-if-error. :immutable-
Если значение равно true, добавляет директиву
immutable.
Все дополнительные пары «ключ-значение» объединяются в директивы. Список поддерживаемых директив Cache-Control см. в статье на MDN.
Примеры
expires_in 10.minutes # => Cache-Control: max-age=600, private expires_in 10.minutes, public: true # => Cache-Control: max-age=600, public expires_in 10.minutes, public: true, must_revalidate: true # => Cache-Control: max-age=600, public, must-revalidate expires_in 1.hour, stale_while_revalidate: 60.seconds # => Cache-Control: max-age=3600, private, stale-while-revalidate=60 expires_in 1.hour, stale_if_error: 5.minutes # => Cache-Control: max-age=3600, private, stale-if-error=300 expires_in 1.hour, public: true, "s-maxage": 3.hours, "no-transform": true # => Cache-Control: max-age=3600, public, s-maxage=10800, no-transform=true
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 309 def expires_now response.cache_control.replace(no_cache: true) end
Устанавливает заголовок HTTP 1.1 Cache-Control со значением no-cache. Это означает, что ресурс будет помечен как устаревший, поэтому клиенты должны всегда повторно проверять его актуальность. Промежуточные кэши и кэши браузеров по-прежнему могут хранить ресурс.
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 137
def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil)
response.cache_control.delete(:no_store)
weak_etag ||= etag || object unless strong_etag
last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
if strong_etag
response.strong_etag = combine_etags strong_etag,
last_modified: last_modified, public: public, template: template
elsif weak_etag || template
response.weak_etag = combine_etags weak_etag,
last_modified: last_modified, public: public, template: template
end
response.last_modified = last_modified if last_modified
response.cache_control[:public] = true if public
response.cache_control.merge!(cache_control)
head :not_modified if request.fresh?(response)
end Устанавливает в ответе etag, last_modified или оба заголовка и возвращает ответ 304 Not Modified, если запрос уже актуален.
Параметры
:etag-
Устанавливает в ответе валидатор «слабого» ETag. См. параметр
:weak_etag. :weak_etag-
Устанавливает в ответе валидатор «слабого» ETag. Запросы с заголовком
If-None-Matchмогут получить ответ304 Not Modified, если ETag совпадает в точности. -
Слабый ETag указывает на семантическую эквивалентность, а не на побайтовое совпадение, поэтому он подходит для кэширования HTML-страниц в кэшах браузеров. Его нельзя использовать для ответов, которые должны быть побайтово идентичными, например при обработке запросов
Rangeдля PDF-файла. :strong_etag-
Устанавливает в ответе валидатор «сильного» ETag. Запросы с заголовком
If-None-Matchмогут получить ответ304 Not Modified, если ETag совпадает в точности. -
Сильный ETag подразумевает точное совпадение: ответ должен быть побайтово идентичным. Например, это необходимо для обработки запросов
Rangeк большому видео- или PDF-файлу, а также для совместимости с некоторыми CDN, которые не поддерживают слабые ETag. :last_modified-
Устанавливает в ответе «слабый» валидатор времени последнего обновления. Последующие запросы с заголовком
If-Modified-Sinceмогут получить ответ304 Not Modified, еслиlast_modified<=If-Modified-Since. :public-
По умолчанию заголовок
Cache-Controlявляется закрытым. Установите для этого параметра значениеtrue, если хотите, чтобы приложение могло кэшироваться на других устройствах, например в прокси-кэшах. :cache_control-
Если параметр задан, он перезапишет существующий заголовок
Cache-Control. Список директивCache-Controlсм. в статье на MDN. :template-
По умолчанию в ETag включается дайджест шаблона для текущего контроллера и действия. Если действие отображает другой шаблон, вместо него можно включить дайджест этого шаблона. Если действие вообще не отображает шаблон, передайте
template: false, чтобы пропустить попытку проверки дайджеста шаблона.
Примеры
def show @article = Article.find(params[:id]) fresh_when(etag: @article, last_modified: @article.updated_at, public: true) end
Будет отправлен ответ 304 Not Modified, если в запросе указаны совпадающие ETag и заголовок If-Modified-Since. В противном случае будет отображён шаблон show.
Можно также просто передать запись:
def show @article = Article.find(params[:id]) fresh_when(@article) end
etag будет установлено в значение записи, а last_modified — в значение updated_at этой записи.
Также можно передать объект, поддерживающий maximum, например коллекцию записей:
def index @articles = Article.all fresh_when(@articles) end
В этом случае etag будет установлено в значение коллекции, а last_modified — в значение maximum(:updated_at) (временную метку последней обновлённой записи).
При передаче записи или коллекции можно по-прежнему указывать другие параметры, например :public и :cache_control:
def show
@article = Article.find(params[:id])
fresh_when(@article, public: true, cache_control: { no_cache: true })
end
Приведённый выше код установит Cache-Control: public, no-cache в ответе.
Если отображается шаблон, отличный от шаблона по умолчанию для контроллера и действия, можно указать, какой дайджест включить в ETag:
before_action { fresh_when @article, template: "widgets/show" }
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 321
def http_cache_forever(public: false)
expires_in 100.years, public: public, immutable: true
yield if stale?(etag: request.fullpath,
last_modified: Time.new(2011, 1, 1).utc,
public: public)
end Кэширует или выполняет блок. Срок действия кэша не должен истекать.
Этот метод можно использовать, если у вас есть HTTP-ответ, который никогда не меняется и который браузер и прокси должны кэшировать бессрочно.
-
public: По умолчанию HTTP-ответы являются закрытыми и кэшируются только в браузере пользователя. Чтобы разрешить прокси кэшировать ответ, установитеtrue, указав тем самым, что кэшированный ответ можно отправлять всем пользователям.
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 355 def must_understand response.cache_control[:must_understand] = true response.cache_control[:no_store] = true end
Добавляет директиву must-understand в заголовок Cache-Control, указывающую, что кэш ДОЛЖЕН понимать семантику полученного кода состояния ответа или отбросить ответ.
Это особенно полезно при отправке ответов с новыми или редко используемыми кодами состояния, которые старые кэши могут интерпретировать неправильно.
Пример
def show
@article = Article.find(params[:id])
if @article.early_access?
must_understand
render status: 203 # Non-Authoritative Information
else
fresh_when @article
end
end
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 331 def no_store response.cache_control.replace(no_store: true) end
Устанавливает заголовок HTTP 1.1 Cache-Control со значением no-store. Это означает, что ресурс нельзя сохранять ни в одном кэше.
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 236 def stale?(object = nil, **freshness_kwargs) fresh_when(object, **freshness_kwargs) !request.fresh?(response) end
Устанавливает в ответе etag и/или last_modified и сравнивает их с данными запроса. Если запрос не соответствует указанным параметрам, он считается устаревшим, и ответ следует сформировать заново. В противном случае запрос считается актуальным и отправляется 304 Not Modified.
Параметры
Список поддерживаемых параметров см. в описании fresh_when.
Примеры
def show
@article = Article.find(params[:id])
if stale?(etag: @article, last_modified: @article.updated_at)
@statistics = @article.really_expensive_call
respond_to do |format|
# all the supported formats
end
end
end
Можно также просто передать запись:
def show
@article = Article.find(params[:id])
if stale?(@article)
@statistics = @article.really_expensive_call
respond_to do |format|
# all the supported formats
end
end
end
etag будет установлено в значение записи, а last_modified — в значение updated_at этой записи.
Также можно передать объект, поддерживающий maximum, например коллекцию записей:
def index
@articles = Article.all
if stale?(@articles)
@statistics = @articles.really_expensive_call
respond_to do |format|
# all the supported formats
end
end
end
В этом случае etag будет установлено в значение коллекции, а last_modified — в значение maximum(:updated_at) (временную метку последней обновлённой записи).
При передаче записи или коллекции можно по-прежнему указывать другие параметры, например :public и :cache_control:
def show
@article = Article.find(params[:id])
if stale?(@article, public: true, cache_control: { no_cache: true })
@statistics = @articles.really_expensive_call
respond_to do |format|
# all the supported formats
end
end
end
Приведённый выше код установит Cache-Control: public, no-cache в ответе.
Если отображается шаблон, отличный от шаблона по умолчанию для контроллера и действия, можно указать, какой дайджест включить в ETag:
def show super if stale?(@article, template: "widgets/show") end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.