新手问题 Gzip 压缩之后如何解压

thxagain · 2016年09月27日 · 最后由 thxagain 回复于 2016年09月29日 · 4300 次阅读

Hi ALL

在和客户端联调,客户端把内容压缩了,我遇到了 HTTP 请求头大概是长这个样子的,我该如何解压呢。

Content-Type: multipart/form-data; boundary=8b612ae9-1e28-40b1-9bd2-eaebe2103643
Connection: Keep-Alive
X-Atlassian-Token: nocheck
Content-Encoding: gzip
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2;)
Accept-Encoding: gzip
Content-Length: 31419

我现在 Console 的结果是

Rack app error handling request 
#<EOFError: EOFError>
/home/gems/rack-2.0.1/lib/rack/multipart/parser.rb:361:in `handle_empty_content!'


gzip 压缩的应该是一些图片,我看到网上的一些压缩方式都是content-type "gzip/json"

如果用 Rails 的话可以用 ActiveSupport::Gzip 去解压,具体可以看http://api.rubyonrails.org/classes/ActiveSupport/Gzip.html#method-c-decompress

如果用 Ruby 的话可以看看 Zlib::GzipReader,Eg:

conn = Zlib::GzipReader.new(StringIO.new(some_gzipped_data))
unzipped = conn.read
conn.close

#2 楼 @mengqing 是用 Rails 的 现在的问题是 连 params 都取不到,感觉在 Rack 层就挂了

理论上应该在反向代理(nginx)那边解压的,App 不应该管这事,就像响应的时候压缩也不是在 App 这做的一样。 如果你需要在 App 这边做,并且 Rails 没能帮你还原请求的话,可能你要在 Rails 的 Rack stack 前自己写个 Rack 中间件做这件事了

#4 楼 @jasl 开发环境没有 nginx,所以就计划写个 Rack 中间件做了。

暂时是这么写的,好像还是没啥效果:

class CompressedRequests
  def initialize(app)
    @app = app
  end

  def method_handled?(env)
    !!(env['REQUEST_METHOD'] =~ /(POST|PUT)/)
  end

  def encoding_handled?(env)
    ['gzip', 'deflate'].include? env['HTTP_CONTENT_ENCODING']
  end

  def call(env)
    if method_handled?(env) && encoding_handled?(env)
      extracted = decode(env['rack.input'], env['HTTP_CONTENT_ENCODING'])

      env.delete('HTTP_CONTENT_ENCODING')
      env['CONTENT_LENGTH'] = extracted.length
      env['rack.input'] = StringIO.new(extracted)
    end

    status, headers, response = @app.call(env)
    return [status, headers, response]
  end

  def decode(input, content_encoding)
    case content_encoding
      when 'gzip' then Zlib::GzipReader.new(input).read
      when 'deflate' then Zlib::Inflate.inflate(input.read)
    end
  end
end

#5 楼 @thxagain 具体情况我不太了解,我大概推测一些注意事项:

  • 这个中间件要先于 Rails 的执行
  • HTTP 协议纯文本的,解压方式正确你应该可以拿到人眼能辨识的明文,就可以判断你解压的代码有没有问题了
  • 确认下解压正确的请求体传递给 Rails 了

不过最好还是架个 nginx。。。这事交给 Ruby 做性能很差。。。

@jasl

谢谢 我昨天在 rails 层已经能够正常解压出来了,中间件那条路一直没走通,在 Controller 层做的解压。

但是如果部署到线上,还是想在 nginx 层做。

想请问下是使用 nginx 的 gunzip 功能么?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号