启用Rack::Deflater后,ETag会发生变化。

6

当启用Rack::Deflater压缩响应正文时,我发现了一些奇怪的问题。也许我漏掉了什么,但启用此功能后,每次请求资源的ETag都会更改,尽管响应已经被压缩。这迫使应用程序每次都需要响应而不是发送304。如果不启用Rack::Deflater,则可以正常工作,并且我已经验证页面源未更改。我正在运行具有thin作为Web服务器的Rails应用程序。

Gemfile.lock https://gist.github.com/2510816

有没有办法让Rack中间件输出更多信息,这样我就能看到发生了什么?

提前感谢。

1个回答

11

所以,我已经解决了最初的问题,但仍未完全获得期望的结果。事实证明,在中间件堆栈中,Rack::Deflater需要放在Rack::ETag之前。仍然不确定为什么这会导致每个请求都更改ETag,但如果我将config.middleware.use "Rack::Deflater"更改为 config.middleware.insert_before "Rack::ETag", "Rack::Deflater",那么ETag就可以在请求之间保持一致。我仍然没有得到304,但我认为这是由于错误的缓存控制头和原始问题无关。希望这能帮助将来遇到类似问题的人。


FYI,Rack::ETag 中间件只是为其获取的任何内容创建标签。将其放在 Rack::Deflater 之后的中间件堆栈中,它将尝试创建压缩数据的哈希值,这是不正确的。 - Michael Slade
是的,这很有道理,但即使它是从压缩数据生成的,如果输入数据和因此压缩的数据没有改变,那么服务器生成的ETag仍然应该保持不变。 - Nick Dancer
只要算法是确定性的,不会添加任何外部数据,那么你就不能指望它们。猜测可能是压缩算法添加了时间戳,或者对其哈希函数进行了随机化处理。 - Michael Slade
7
找到了。GzipWriterRack::Deflater使用的压缩工具,它会给所有被压缩的内容加上时间戳。 - Michael Slade
好的,现在我明白多了。感谢你的解释。 - Nick Dancer
实际上,基于压缩数据的ETag是正确的。相同ETag的响应体应该是逐字节可比的。否则,应使用弱ETag验证器,例如“ETag:W /”#{md5(non-gzip-body())}“。”。 - mlangenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接