1

В небольшом стремлении улучшить кеширование в приложении Rails (3.2) я заметил, что заголовок Etag изменяется для каждого отдельного запроса.ETag меняется при каждом запросе. Интерференция промежуточного программного обеспечения стойки?

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

use Rack::Cache 
use ActionDispatch::Static 
use Rack::Lock 
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007f462e790e98> 
use Rack::Runtime 
use Rack::MethodOverride 
use ActionDispatch::RequestId 
use Rails::Rack::Logger 
use ActionDispatch::ShowExceptions 
use ActionDispatch::DebugExceptions 
use ActionDispatch::RemoteIp 
use ActionDispatch::Callbacks 
use ActiveRecord::ConnectionAdapters::ConnectionManagement 
use ActiveRecord::QueryCache 
use ActionDispatch::Cookies 
use ActionDispatch::Session::CookieStore 
use ActionDispatch::Flash 
use ActionDispatch::ParamsParser 
use ActionDispatch::Head 
use Rack::ConditionalGet 
use Rack::Deflater 
use Rack::ETag 
use ActionDispatch::BestStandardsSupport 
use Warden::Manager 
use Rack::Attack 
use Rack::SslEnforcer 
use HireFire::Middleware` 

После некоторых исследований я наткнулся на некоторую информацию, которая Rack :: Deflater генерирует метку времени для всего она сдувается. Я попытался переместить Rack :: Deflater после Rack :: ETag (config.middleware.insert_after Rack::ETag, Rack::Deflater), но заголовок ETag по-прежнему изменяется при каждом запросе.

Любой, у кого больше опыта работы в стойке, кто может помочь мне узнать, что вызывает такое поведение?

+0

Хорошо, давайте начнем со следующего. 'ETag' должен быть до' Deflater'. Это уж точно. Вы можете попытаться подключиться к промежуточному программному обеспечению ETag с помощью отладчика и попытаться проанализировать полученный контент. Пара запросов, и вы найдете динамическую часть. – marvelousNinja

+0

Вы уверены, что 'ETag' должен быть до' Deflater'? Если я вставляю 'Deflater' после' ETag', то объект body, используемый для вычисления дайджеста, представляет собой «Rack :: Deflater :: GzipStream» с меткой времени и всеми. Если я делаю наоборот, объект body - это «ActionDispatch :: Response», который, кажется, будет одинаковым каждый раз, по крайней мере, в разработке. – rogerkk

+0

Просто для того, чтобы правильно понимать друг друга, 'before' я подразумеваю, что' ETag' должен быть обработан *** до *** 'Deflater' по причинам, указанным выше. «ActionDispath :: Response» кажется одинаковым каждый раз? Предполагая, что 'ETag' вычисляется на основе тела ответа, вам нужно подключиться к этому процессу и проверить это точно. Я отвечу некоторые детали в свой ответ. – marvelousNinja

ответ

5

Вот соответствующий исходный код Rack::ETag:

def call(env) 
    status, headers, body = @app.call(env) 

    if etag_status?(status) && etag_body?(body) && !skip_caching?(headers) 
    original_body = body 
    digest, new_body = digest_body(body) 
    body = Rack::BodyProxy.new(new_body) do 
     original_body.close if original_body.respond_to?(:close) 
    end 
    headers['ETag'] = %("#{digest}") if digest 
    end 

    unless headers['Cache-Control'] 
    if digest 
     headers['Cache-Control'] = @cache_control if @cache_control 
    else 
     headers['Cache-Control'] = @no_cache_control if @no_cache_control 
    end 
    end 

    [status, headers, body] 
end 

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

def digest_body(body) 
    parts = [] 
    digest = nil 

    body.each do |part| 
    parts << part 
    (digest ||= Digest::MD5.new) << part unless part.empty? 
    end 

    [digest && digest.hexdigest, parts] 
end 

Вы можете зацепить этот метод. Я считаю, что вы обнаружите, что в вашем ответе есть что-то динамичное, и это блокирует использование заголовка ETag. Например, в ваших формах могут быть маркеры защиты CSRF или что-то в этом роде. Я бы настоятельно предложил вам использовать что-то вроде debugger или pry для размещения точек останова.

+0

Действительно, я нашел что-то скрывающее: новое связующее ПО Relic, которое вставляет информацию о времени в каждом ответе. Ваш ответ заставил меня углубиться в исходный код, и я наткнулся на это. Благодаря! – rogerkk

Смежные вопросы

 Смежные вопросы