class HTTP2::Header::Decompressor
Responsible for decoding received headers and maintaining compression context of the opposing peer. Decompressor
must be initialized with appropriate starting context based on local role: client or server.
@example
server_role = Decompressor.new(:request) client_role = Decompressor.new(:response)
Public Class Methods
@param options [Hash] decoding options. Only :table_size is effective.
# File lib/http/2/compressor.rb, line 472 def initialize(**options) @cc = EncodingContext.new(**options) end
Public Instance Methods
Decodes and processes header commands within provided buffer.
@param buf [Buffer] @return [Array] +[[name, value], …]+
# File lib/http/2/compressor.rb, line 555 def decode(buf) list = [] decoding_pseudo_headers = true until buf.empty? next_header = @cc.process(header(buf)) next if next_header.nil? is_pseudo_header = next_header.first.start_with? ':' if !decoding_pseudo_headers && is_pseudo_header fail ProtocolError, 'one or more pseudo headers encountered after regular headers' end decoding_pseudo_headers = is_pseudo_header list << next_header end list end
Decodes header command from provided buffer.
@param buf [Buffer] @return [Hash] command
# File lib/http/2/compressor.rb, line 520 def header(buf) peek = buf.readbyte(0) header = {} header[:type], type = HEADREP.find do |_t, desc| mask = (peek >> desc[:prefix]) << desc[:prefix] mask == desc[:pattern] end fail CompressionError unless header[:type] header[:name] = integer(buf, type[:prefix]) case header[:type] when :indexed fail CompressionError if (header[:name]).zero? header[:name] -= 1 when :changetablesize header[:value] = header[:name] else if (header[:name]).zero? header[:name] = string(buf) else header[:name] -= 1 end header[:value] = string(buf) end header end
Decodes integer value from provided buffer.
@param buf [String] @param n [Integer] number of available bits @return [Integer]
# File lib/http/2/compressor.rb, line 487 def integer(buf, n) limit = 2**n - 1 i = !n.zero? ? (buf.getbyte & limit) : 0 m = 0 while (byte = buf.getbyte) i += ((byte & 127) << m) m += 7 break if (byte & 128).zero? end if (i == limit) i end
Decodes string value from provided buffer.
@param buf [String] @return [String] UTF-8 encoded string @raise [CompressionError] when input is malformed
# File lib/http/2/compressor.rb, line 507 def string(buf) huffman = (buf.readbyte(0) & 0x80) == 0x80 len = integer(buf, 7) str = buf.read(len) fail CompressionError, 'string too short' unless str.bytesize == len str = Huffman.new.decode(Buffer.new(str)) if huffman str.force_encoding(Encoding::UTF_8) end
Set dynamic table size in EncodingContext
@param size [Integer] new dynamic table size
# File lib/http/2/compressor.rb, line 478 def table_size=(size) @cc.table_size = size end