Как проверить рельсы ETag на кеширование? - PullRequest
8 голосов
/ 15 апреля 2010

Можно ли покрыть мой контроллер, который сильно зависит от Etags, модульными тестами?

Вот что я пытаюсь сделать: в случае, если страница не устарела (имеется в виду, что она свежая), я добавляю заголовок к ответу.

Когда я пытаюсь все это протестировать (rspec), независимо от того, сколько у меня схожих запросов, я все равно получаю 200 OK вместо 304, и мой заголовок не изменяется. Кроме того, если я отслеживаю request.fresh? (Ответ), это ВСЕГДА ложно.

Тем не менее, он отлично работает в браузере. Я уже пытался указать ActionController :: Base.perform_caching = true, это не меняет общую ситуацию.

Спасибо

Ответы [ 6 ]

9 голосов
/ 12 марта 2013

Вот как вы можете проверить, возвращает ли второй запрос ответ 304:

    get action, params
    assert_response 200, @response.body
    etag = @response.headers["ETag"]
    @request.env["HTTP_IF_NONE_MATCH"] = etag
    get action, params
    assert_response 304, @response.body
4 голосов
/ 08 сентября 2011

Rails хэширует: etag, который вы предоставляете:

headers['ETag'] = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(etag))}")

так что установите что-то простое, как

frash_when(:etag => 'foo')

будет вызвано только правым дайджестом (необходимы двойные кавычки)

def with_etag
  if stale?(:etag => 'foo')
    render :text => 'OK'
  end
end

... tested by ...

@request.env['HTTP_IF_NONE_MATCH'] = '"acbd18db4cc2f85cedef654fccc4a4d8"'
get :with_etag
assert_equal 304, @response.status.to_i

То же самое для модифицированного:

def with_modified
  if stale?(:last_modified => 1.minute.ago)
    render :text => 'OK'
  end
end

... tested by ...

@request.env['HTTP_IF_MODIFIED_SINCE'] = 2.minutes.ago.rfc2822
get :with_modified
assert_equal 304, @response.status.to_i
4 голосов
/ 15 апреля 2010

Хорошо, вот точка:

Прежде чем выполнить запрос, прочитайте все, что связано с ETag в коде Rails и не забудьте установить:

request.env["HTTP_IF_MODIFIED_SINCE"]
request.env["HTTP_IF_NONE_MATCH"]

Так как они необходимы для тестирования ETag.

1 голос
/ 28 мая 2013

Этот гист очень полезен для тестирования ретагов в rspec -

https://gist.github.com/brettfishman/3868277

0 голосов
/ 25 апреля 2019

По крайней мере, в Rails 5.2 решение szeryf не работает. Этот вариант работает:

get action, parms
assert_response 200, @response.code
etag = @response.headers["ETag"]
get action, parms, headers: { "HTTP_IF_NONE_MATCH": etag }
assert_response 304, @response.code

См. Направляющие рельсов: https://guides.rubyonrails.org/testing.html#setting-headers-and-cgi-variables

0 голосов
/ 19 февраля 2015

Rails 4.2 теперь также принимает во внимание дайджест шаблона. У меня сработало следующее:

def calculate_etag(record, template)
  Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key([
    record,
    controller.send(:lookup_and_digest_template, template)
  ])).inspect
end

def set_cache_headers(modified_since: nil, record: nil, template: nil)
  request.if_modified_since = modified_since.rfc2822
  request.if_none_match = calculate_etag(record, template)
end

set_cache_headers(
  modified_since: 2.days.ago,
  record: @book,
  template: 'books/index'
)
...