removed the compression modules from the transcoders, using them directly in the plugin, rewrote the encoder to be more interchangeable

This commit is contained in:
HoneyryderChuck 2018-01-14 22:46:28 +00:00
parent 72b90c3f17
commit dcd90b706a
4 changed files with 127 additions and 125 deletions

View File

@ -15,17 +15,28 @@ module HTTPX
end end
end end
module RequestBodyMethods
def initialize(*)
super
return if @body.nil?
@headers.get("content-encoding").each do |encoding|
@body = Encoder.new(@body, Compression.registry(encoding).encoder)
end
@headers["content-length"] = @body.bytesize unless chunked?
end
end
module ResponseBodyMethods module ResponseBodyMethods
def initialize(*) def initialize(*)
super super
@_decoders = @headers.get("content-encoding").map do |encoding| @_decoders = @headers.get("content-encoding").map do |encoding|
Transcoder.registry(encoding).decoder Compression.registry(encoding).decoder
end end
@_compressed_length = if @headers.key?("content-length") @_compressed_length = if @headers.key?("content-length")
@headers["content-length"].to_i @headers["content-length"].to_i
else else
Float::INFINITY Float::INFINITY
end end
end end
def write(chunk) def write(chunk)
@ -50,6 +61,47 @@ module HTTPX
end end
end end
class Encoder
def initialize(body, deflater)
@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)
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 class Decoder
extend Forwardable extend Forwardable
@ -65,41 +117,6 @@ module HTTPX
@inflater.inflate(chunk) @inflater.inflate(chunk)
end end
end end
class CompressEncoder
attr_reader :content_type
def initialize(raw, encoder)
@content_type = raw.content_type
@raw = raw.respond_to?(:read) ? raw : StringIO.new(raw.to_s)
@buffer = StringIO.new("".b, File::RDWR)
@encoder = encoder
end
def each(&blk)
return enum_for(__method__) unless block_given?
unless @buffer.size.zero?
@buffer.rewind
return @buffer.each(&blk)
end
@encoder.compress(@raw, @buffer, chunk_size: 16_384, &blk)
end
def to_s
compress
@buffer.rewind
@buffer.read
end
def bytesize
@encoder.compress(@raw, @buffer, chunk_size: 16_384)
@buffer.size
end
def close
# @buffer.close
end
end
end end
register_plugin :compression, Compression register_plugin :compression, Compression
end end

View File

@ -11,16 +11,13 @@ module HTTPX
end end
def self.configure(*) def self.configure(*)
Transcoder.register "br", BrotliTranscoder
Compression.register "br", self Compression.register "br", self
end end
module Encoder module Encoder
module_function module_function
def compress(raw, buffer, chunk_size: ) def deflate(raw, buffer, chunk_size: )
return unless buffer.size.zero?
raw.rewind
begin begin
while chunk = raw.read(chunk_size) while chunk = raw.read(chunk_size)
compressed = ::Brotli.deflate(chunk) compressed = ::Brotli.deflate(chunk)
@ -43,16 +40,14 @@ module HTTPX
end end
end end
module BrotliTranscoder module_function
module_function
def encode(payload) def encoder
CompressEncoder.new(payload, Encoder) Encoder
end end
def decoder def decoder
Decoder.new(BrotliWrapper) Decoder.new(BrotliWrapper)
end
end end
end end
end end

View File

@ -10,45 +10,40 @@ module HTTPX
end end
def self.configure(*) def self.configure(*)
Transcoder.register "deflate", DeflateTranscoder
Compression.register "deflate", self Compression.register "deflate", self
end end
module DeflateTranscoder module Encoder
module Encoder
module_function
def compress(raw, buffer, chunk_size: )
return unless buffer.size.zero?
raw.rewind
begin
deflater = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
Zlib::MAX_WBITS,
Zlib::MAX_MEM_LEVEL,
Zlib::HUFFMAN_ONLY)
while chunk = raw.read(chunk_size)
compressed = deflater.deflate(chunk)
buffer << compressed
yield compressed if block_given?
end
last = deflater.finish
buffer << last
yield last if block_given?
ensure
deflater.close
end
end
end
module_function module_function
def encode(payload) def deflate(raw, buffer, chunk_size: )
CompressEncoder.new(payload, Encoder) begin
deflater = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
Zlib::MAX_WBITS,
Zlib::MAX_MEM_LEVEL,
Zlib::HUFFMAN_ONLY)
while chunk = raw.read(chunk_size)
compressed = deflater.deflate(chunk)
buffer << compressed
yield compressed if block_given?
end
last = deflater.finish
buffer << last
yield last if block_given?
ensure
deflater.close
end
end end
end
def decoder module_function
Decoder.new(Zlib::Inflate.new(32 + Zlib::MAX_WBITS))
end def encoder
Encoder
end
def decoder
Decoder.new(Zlib::Inflate.new(32 + Zlib::MAX_WBITS))
end end
end end
end end

View File

@ -11,55 +11,50 @@ module HTTPX
end end
def self.configure(*) def self.configure(*)
Transcoder.register "gzip", GZIPTranscoder
Compression.register "gzip", self Compression.register "gzip", self
end end
module GZIPTranscoder class Encoder
class Encoder def deflate(raw, buffer, chunk_size: )
def compress(raw, buffer, chunk_size: ) begin
return unless buffer.size.zero? gzip = Zlib::GzipWriter.new(self)
raw.rewind
begin
gzip = Zlib::GzipWriter.new(self)
while chunk = raw.read(chunk_size) while chunk = raw.read(chunk_size)
gzip.write(chunk) gzip.write(chunk)
gzip.flush gzip.flush
compressed = compressed_chunk compressed = compressed_chunk
buffer << compressed buffer << compressed
yield compressed if block_given? yield compressed if block_given?
end
ensure
gzip.close
end end
end
private
def write(chunk)
@compressed_chunk = chunk
end
def compressed_chunk
compressed = @compressed_chunk
compressed
ensure ensure
@compressed_chunk = nil gzip.close
end end
end end
private
module_function def write(chunk)
@compressed_chunk = chunk
def encode(payload)
CompressEncoder.new(payload, Encoder.new)
end end
def decoder def compressed_chunk
Decoder.new(Zlib::Inflate.new(32 + Zlib::MAX_WBITS)) compressed = @compressed_chunk
compressed
ensure
@compressed_chunk = nil
end end
end end
module_function
def encoder
Encoder.new
end
def decoder
Decoder.new(Zlib::Inflate.new(32 + Zlib::MAX_WBITS))
end
end end
end end
register_plugin :"compression/gzip", Compression::GZIP register_plugin :"compression/gzip", Compression::GZIP