config.ru考虑在使用 Rails 时不要放入 Rack 中间件
从Rails 2开始,Rails 就有了自己的中间件堆栈管理器。
正确的方法是:
# config/application.rb or config/environment.rb depends on your Rails version
config.middleware.use Rack::Deflater
使用时不要使用@djcp的解决方案Rack::ETag
简短的回答:
module MyApp
class Application < Rails::Application
config.middleware.insert_before Rack::ETag, Rack::Deflater
end
end
Rack::Deflater和的顺序Rack::ETag很重要,因为Rack::Deflater用于Zlib::GzipWriter压缩响应正文,默认情况下会使用时间戳进行压缩,这意味着即使原始响应正文相同,压缩后的响应正文也会每秒更改一次。
要重现此问题,请运行以下脚本:
require 'rack/etag'
require 'rack/deflater'
require 'rack/content_length'
@app = Rack::Builder.new do
use Rack::ETag
use Rack::Deflater
use Rack::ContentLength
run ->(*) { [200, {}, ['hello world']] }
end
def puts_etag
puts @app.call({ 'HTTP_ACCEPT_ENCODING' => 'gzip' })[1]['ETag']
end
puts_etag
sleep 1
puts_etag
可以简单地交换 and 的行Rack::ETag并Rack::Deflater获得预期的输出。
RailsRack::ETag默认使用并且config.middleware.use只是追加。Rack::Deflater要在之前插入Rack::Etag,请config.middleware.insert_before改用。