1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
# frozen_string_literal: true
# Released under the MIT License.
# Copyright, 2019-2025, by Samuel Williams.
require "zlib"
require_relative "deflate"
module Protocol
module HTTP
module Body
# A body which decompresses the contents using the DEFLATE or GZIP algorithm.
class Inflate < ZStream
# Create a new body which decompresses the given body using the GZIP algorithm by default.
#
# @parameter body [Readable] the body to wrap.
# @parameter window_size [Integer] the window size to use for decompression.
def self.for(body, window_size = GZIP)
self.new(body, Zlib::Inflate.new(window_size))
end
# Read from the underlying stream and inflate it.
#
# @returns [String | Nil] the inflated data, or nil if the stream is finished.
def read
if stream = @stream
# Read from the underlying stream and inflate it:
while chunk = super
@input_length += chunk.bytesize
# It's possible this triggers the stream to finish.
chunk = stream.inflate(chunk)
break unless chunk&.empty?
end
if chunk
@output_length += chunk.bytesize
elsif !stream.closed?
chunk = stream.finish
@output_length += chunk.bytesize
end
# If the stream is finished, we need to close it and potentially return nil:
if stream.finished?
@stream = nil
stream.close
while super
# There is data left in the stream, so we need to keep reading until it's all consumed.
end
if chunk.empty?
return nil
end
end
return chunk
end
end
end
end
end
end
|