Des ETAG faibles dans les rails?

Quelle est la meilleure façon de dire aux rails d’utiliser des ETAG faibles plutôt que forts lors de l’utilisation de méthodes fresh_when et stale? ?

La raison pour laquelle je pose cette question est que nginx (correctement) supprime les en-têtes ETAG puissants des réponses lorsque l’activation gzip à la volée est activée .

    J’ai pris le code de la réponse de @ grosser et l’ai transformé en gemme:

    Vous pouvez simplement append ceci à votre fichier gemfile:

     gem 'rails_weak_etags' 

    Et il sera installé dans votre middleware avant Rack::ConditionalGet :

     > bundle exec rake middleware .... use RailsWeakEtags::Middleware use Rack::ConditionalGet use Rack::ETag .... 

    Ensuite, toutes les étiquettes électroniques générées par les rails, avec Rack :: ETag ou avec des étiquettes électroniques explicites, seront converties en faibles. En utilisant un patch ou une version> 1.7.3 de nginx, vous pourrez alors utiliser les balises électroniques et la compression gzip.

    RACK 1.6 par défaut etags à faiblesse – ce bijou n’est plus utile si vous effectuez une mise à niveau.

    middleware:

     class WeakEtagMiddleware def initialize(app) @app = app end def call(env) # make request etags "strong" etag = env['HTTP_IF_NONE_MATCH'] if etag && etag =~ /^W\// env['HTTP_IF_NONE_MATCH'] = etag[2..-1] end status, headers, body = @app.call(env) # make response etags "weak" etag = headers['ETag'] if etag && etag !~ /^W\// headers['ETag'] = "W/#{etag}" end [status, headers, body] end end 

    plus append un middleware

     Rails.application.config.middleware.insert_before(Rack::ETag, WeakEtagMiddleware) 

    Plus tests unitaires

     context WeakEtagMiddleware do let(:backend) { Rack::ConditionalGet.new(Rack::ETag.new(lambda { |env| [env["status"] || 200, {}, ["XXX"]] })) } let(:app) { WeakEtagMiddleware.new(backend) } let(:expected_digest_1) { "bc9189406be84ec297464a514221406d" } let(:env) { {"REQUEST_METHOD" => "GET"} } should "converts etags to weak" do status, headers, body = app.call(env) assert_equal %{W/"#{expected_digest_1}"}, headers["ETag"] assert_equal status, 200 end should "not add etags to responses without etag" do status, headers, body = app.call(env.merge("status" => 400)) refute headers["ETag"] assert_equal status, 400 end should "recognize weak ETags" do status, headers, body = app.call(env.merge("HTTP_IF_NONE_MATCH" => %{W/"#{expected_digest_1}"})) assert_equal status, 304 end should "not recognize invalid ETags" do status, headers, body = app.call(env.merge("HTTP_IF_NONE_MATCH" => %{W/"something-not-fresh"})) assert_equal status, 200 end end 

    plus des tests d’intégration

     require_relative "../helpers/test_helper" class WeakEtagsTest < ActionController::IntegrationTest class TestController < ActionController::Base def auto render :text => "XXX" end def fresh if stale? :etag => "YYY" render :text => "XXX" end end end additional_routes do get '/test/weak_etags/:action', :controller => 'weak_etags_test/test' end fixtures :accounts, :users context "weak etags" do let(:expected_digest_1) { "bc9189406be84ec297464a514221406d" } let(:expected_digest_2) { "fd7c5c4fdaa97163ee4ba8842baa537a" } should "auto adds weak etags" do get "/test/weak_etags/auto" assert_equal "XXX", @response.body assert_equal %{W/"#{expected_digest_1}"}, @response.headers["ETag"] end should "adds weak etags through fresh_when" do get "/test/weak_etags/fresh" assert_equal "XXX", @response.body assert_equal %{W/"#{expected_digest_2}"}, @response.headers["ETag"] end should "recognize auto-added ETags" do get "/test/weak_etags/auto", {}, {"HTTP_IF_NONE_MATCH" => %{W/"#{expected_digest_1}"}} assert_response :not_modified end should "recognize fresh ETags" do get "/test/weak_etags/fresh", {}, {"HTTP_IF_NONE_MATCH" => %{W/"#{expected_digest_2}"}} assert_response :not_modified end end end 

    Voici une alternative qui évite d’apporter des modifications à votre serveur d’applications. Cette directive convertit tous les etags retournés par votre application en etags faibles avant qu’ils ne soient supprimés de la réponse. Mettez-le à l’intérieur de votre nginx config:

     location / { add_header ETag "W/$sent_http_ETAG"; } 

    J’ai vérifié que cela fonctionne avec nginx 1.7.6.