【问题标题】:Ruby Net::HTTP not decoding gzip?Ruby Net::HTTP 不解码 gzip?
【发布时间】:2024-01-10 23:00:01
【问题描述】:

我有 ruby-1.9.3-p327 安装了 zlib。 localhost:80是nginx简单测试页面。

require "net/http"
=> true
Net::HTTP::HAVE_ZLIB
=> true

res = Net::HTTP.start("localhost", "80") do |http|
  req = Net::HTTP::Get.new "/"
  req["accept-encoding"] = "gzip"
  http.request req
end
=> #<Net::HTTPOK 200 OK readbody=true>

res.get_fields "content-encoding"
=> ["gzip"]
res.body
=> "\x1F\x8B\b\x00\x00\x00\x00\x00\x00\x03\xEC\xBDi..."

尸体没有被解码。为什么?

【问题讨论】:

  • 切换到 ruby-head (2.0) 后生效

标签: ruby nginx gzip


【解决方案1】:

对于在 ruby​​ 1.9 上运行代码时遇到问题并且无法升级到 ruby​​ 2.0 的任何人,只需将该代码包含到您的项目中即可。

module HTTPResponseDecodeContentOverride
  def initialize(h,c,m)
    super(h,c,m)
    @decode_content = true
  end
  def body
    res = super
    if self['content-length']
      self['content-length']= res.bytesize
    end
    res
  end
end
module Net
  class HTTPResponse
    prepend HTTPResponseDecodeContentOverride
  end
end

【讨论】:

  • 你拯救了我的一天!谢谢
  • 对此的根本原因有什么想法吗?
  • ruby 2.0 代码在 "@decode_content" 设置为 true 之前不会进行 gzip 解码。
  • 和 @decode_content 默认为 false。加上不改变内容长度,解码的长度不等于转移 - 这就是为什么我也覆盖了它
  • 为什么要覆盖 body 方法?
【解决方案2】:

如果您使用http.get,它应该会自动解码,但看起来request 可能不适合您。

这里显然有解压gzip请求的代码,但只针对get方法: https://github.com/ruby/ruby/blob/v1_9_3_327/lib/net/http.rb#L1031

【讨论】:

    【解决方案3】:

    根据我的实验,发生这种情况的至少一个原因是right_http_connection gem。我测试了 1.3.0 和 1.4.0 版本。这个 gem monkey 修补 Net::HTTP 并导致解码 GZipped 响应出现问题。

    您可以在this GitHub issue 中阅读有关此问题的更多信息。

    【讨论】:

    • 是的,你应该先检查你的 Gemfile。包括right_awsright_http_connection 将破坏Net::HTTP。这些库未维护,不兼容 2.0。 aws-sdk 是使用 AWS 的推荐方式。
    【解决方案4】:

    我认为它不会自动完成。

    要解码,试试下面的sn-p(假设响应是StringIO):

    begin
      Zlib::GzipReader.new(response).read
    rescue Zlib::GzipFile::Error, Zlib::Error # Not gzipped
      response.rewind
      response.read
    end
    

    【讨论】: