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
改用。