lib/httpx/plugins/compression.rb in httpx-0.9.0 vs lib/httpx/plugins/compression.rb in httpx-0.10.0
- old
+ new
@@ -44,20 +44,17 @@
module RequestBodyMethods
def initialize(*, options)
super
return if @body.nil?
- if (threshold = options.compression_threshold_size)
- unless unbounded_body?
- return if @body.bytesize < threshold
- end
- end
+ threshold = options.compression_threshold_size
+ return if threshold && !unbounded_body? && @body.bytesize < threshold
@headers.get("content-encoding").each do |encoding|
next if encoding == "identity"
- @body = Encoder.new(@body, Compression.registry(encoding).encoder)
+ @body = Encoder.new(@body, Compression.registry(encoding).deflater)
end
@headers["content-length"] = @body.bytesize unless chunked?
end
end
@@ -69,114 +66,82 @@
super
return unless @headers.key?("content-encoding")
- @_decoders = @headers.get("content-encoding").map do |encoding|
+ # remove encodings that we are able to decode
+ @headers["content-encoding"] = @headers.get("content-encoding") - @encodings
+
+ compressed_length = if @headers.key?("content-length")
+ @headers["content-length"].to_i
+ else
+ Float::INFINITY
+ end
+
+ @_inflaters = @headers.get("content-encoding").map do |encoding|
next if encoding == "identity"
- decoder = Compression.registry(encoding).decoder
+ inflater = Compression.registry(encoding).inflater(compressed_length)
# do not uncompress if there is no decoder available. In fact, we can't reliably
# continue decompressing beyond that, so ignore.
- break unless decoder
+ break unless inflater
@encodings << encoding
- decoder
+ inflater
end.compact
- # remove encodings that we are able to decode
- @headers["content-encoding"] = @headers.get("content-encoding") - @encodings
-
- @_compressed_length = if @headers.key?("content-length")
- @headers["content-length"].to_i
- else
- Float::INFINITY
- end
+ # this can happen if the only declared encoding is "identity"
+ remove_instance_variable(:@_inflaters) if @_inflaters.empty?
end
def write(chunk)
- return super unless defined?(@_compressed_length)
+ return super unless defined?(@_inflaters)
- @_compressed_length -= chunk.bytesize
chunk = decompress(chunk)
super(chunk)
end
- def close
- super
-
- return unless defined?(@_decoders)
-
- @_decoders.each(&:close)
- end
-
private
def decompress(buffer)
- @_decoders.reverse_each do |decoder|
- buffer = decoder.decode(buffer)
- buffer << decoder.finish if @_compressed_length <= 0
+ @_inflaters.reverse_each do |inflater|
+ buffer = inflater.inflate(buffer)
end
buffer
end
end
class Encoder
+ attr_reader :content_type
+
def initialize(body, deflater)
+ @content_type = body.content_type
@body = body.respond_to?(:read) ? body : StringIO.new(body.to_s)
@buffer = StringIO.new("".b, File::RDWR)
@deflater = deflater
end
def each(&blk)
return enum_for(__method__) unless block_given?
- unless @buffer.size.zero?
- @buffer.rewind
- return @buffer.each(&blk)
- end
- deflate(&blk)
+ return deflate(&blk) if @buffer.size.zero?
+
+ @buffer.rewind
+ @buffer.each(&blk)
end
def bytesize
deflate
@buffer.size
end
- def to_s
- deflate
- @buffer.rewind
- @buffer.read
- end
-
- def close
- @buffer.close
- @body.close
- end
-
private
def deflate(&blk)
return unless @buffer.size.zero?
@body.rewind
@deflater.deflate(@body, @buffer, chunk_size: 16_384, &blk)
- end
- end
-
- class Decoder
- extend Forwardable
-
- def_delegator :@inflater, :finish
-
- def_delegator :@inflater, :close
-
- def initialize(inflater)
- @inflater = inflater
- end
-
- def decode(chunk)
- @inflater.inflate(chunk)
end
end
end
register_plugin :compression, Compression
end