Class: Chef::HTTP::Decompressor

Inherits:
Object
  • Object
show all
Defined in:
lib/chef/http/decompressor.rb

Overview

Middleware-esque class for handling compression in HTTP responses.

Defined Under Namespace

Classes: DeflateInflater, GzipInflater, NoopInflater

Constant Summary collapse

CONTENT_ENCODING =
"content-encoding".freeze
GZIP =
"gzip".freeze
DEFLATE =
"deflate".freeze
IDENTITY =
"identity".freeze

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Decompressor

Returns a new instance of Decompressor


53
54
55
56
# File 'lib/chef/http/decompressor.rb', line 53

def initialize(opts = {})
  @disable_gzip = false
  handle_options(opts)
end

Instance Method Details

#decompress_body(response) ⇒ Object


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/chef/http/decompressor.rb', line 76

def decompress_body(response)
  if gzip_disabled? || response.body.nil?
    response.body
  else
    case response[CONTENT_ENCODING]
    when GZIP
      Chef::Log.debug "Decompressing gzip response"
      Zlib::Inflate.new(Zlib::MAX_WBITS + 16).inflate(response.body)
    when DEFLATE
      Chef::Log.debug "Decompressing deflate response"
      Zlib::Inflate.inflate(response.body)
    else
      response.body
    end
  end
end

#gzip_disabled?Boolean

gzip is disabled using the disable_gzip => true option in the constructor. When gzip is disabled, no 'Accept-Encoding' header will be set, and the response will not be decompressed, no matter what the Content-Encoding header of the response is. The intended use case for this is to work around situations where you request +file.tar.gz+, but the server responds with a content type of tar and a content encoding of gzip, tricking the client into decompressing the response so you end up with a tar archive (no gzip) named file.tar.gz

Returns:

  • (Boolean)

125
126
127
# File 'lib/chef/http/decompressor.rb', line 125

def gzip_disabled?
  @disable_gzip
end

#handle_request(method, url, headers = {}, data = false) ⇒ Object


58
59
60
61
# File 'lib/chef/http/decompressor.rb', line 58

def handle_request(method, url, headers = {}, data = false)
  headers[HTTPRequest::ACCEPT_ENCODING] = HTTPRequest::ENCODING_GZIP_DEFLATE unless gzip_disabled?
  [method, url, headers, data]
end

#handle_response(http_response, rest_request, return_value) ⇒ Object


63
64
65
66
67
68
69
70
# File 'lib/chef/http/decompressor.rb', line 63

def handle_response(http_response, rest_request, return_value)
  # temporary hack, skip processing if return_value is false
  # needed to keep conditional get stuff working correctly.
  return [http_response, rest_request, return_value] if return_value == false
  response_body = decompress_body(http_response)
  http_response.body.replace(response_body) if http_response.body.respond_to?(:replace)
  [http_response, rest_request, return_value]
end

#handle_stream_complete(http_response, rest_request, return_value) ⇒ Object


72
73
74
# File 'lib/chef/http/decompressor.rb', line 72

def handle_stream_complete(http_response, rest_request, return_value)
  [http_response, rest_request, return_value]
end

#stream_response_handler(response) ⇒ Object

This isn't used when this class is used as middleware; it returns an object you can use to unzip/inflate a streaming response.


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/chef/http/decompressor.rb', line 95

def stream_response_handler(response)
  if gzip_disabled?
    Chef::Log.debug "disable_gzip is set. \
      Not using #{response[CONTENT_ENCODING]} \
      and initializing noop stream deflator."
    NoopInflater.new
  else
    case response[CONTENT_ENCODING]
    when GZIP
      Chef::Log.debug "Initializing gzip stream deflator"
      GzipInflater.new
    when DEFLATE
      Chef::Log.debug "Initializing deflate stream deflator"
      DeflateInflater.new
    else
      Chef::Log.debug "content_encoding = '#{response[CONTENT_ENCODING]}' \
        initializing noop stream deflator."
      NoopInflater.new
    end
  end
end