Class: HTTP2::Header::Decompressor
- Inherits:
-
Object
- Object
- HTTP2::Header::Decompressor
- Includes:
- BufferUtils, Error
- Defined in:
- lib/http/2/header/decompressor.rb
Overview
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.
Constant Summary collapse
- FORBIDDEN_HEADERS =
%w[connection te].freeze
Instance Method Summary collapse
-
#decode(buf, frame = nil) ⇒ Array
Decodes and processes header commands within provided buffer.
-
#header(buf) ⇒ Hash
Decodes header command from provided buffer.
-
#initialize(options = {}) ⇒ Decompressor
constructor
A new instance of Decompressor.
-
#integer(buf, n) ⇒ Integer
Decodes integer value from provided buffer.
-
#string(buf) ⇒ String
Decodes string value from provided buffer.
-
#table_size=(size) ⇒ Object
Set dynamic table size in EncodingContext.
Methods included from BufferUtils
#read_str, #read_uint32, #shift_byte
Constructor Details
#initialize(options = {}) ⇒ Decompressor
Returns a new instance of Decompressor.
17 18 19 |
# File 'lib/http/2/header/decompressor.rb', line 17 def initialize( = {}) @cc = EncodingContext.new() end |
Instance Method Details
#decode(buf, frame = nil) ⇒ Array
Decodes and processes header commands within provided buffer.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/http/2/header/decompressor.rb', line 109 def decode(buf, frame = nil) list = [] decoding_pseudo_headers = true @cc.listen_on_table do until buf.empty? field, value = @cc.process(header(buf)) next if field.nil? is_pseudo_header = field.start_with? ":" if !decoding_pseudo_headers && is_pseudo_header raise ProtocolError, "one or more pseudo headers encountered after regular headers" end decoding_pseudo_headers = is_pseudo_header raise ProtocolError, "invalid header received: #{field}" if FORBIDDEN_HEADERS.include?(field) if frame case field when ":status" frame[:status] = Integer(value) when ":method" frame[:method] = value when "content-length" frame[:content_length] = Integer(value) when "trailer" (frame[:trailer] ||= []) << value end end list << [field, value] end end list end |
#header(buf) ⇒ Hash
Decodes header command from provided buffer.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/http/2/header/decompressor.rb', line 70 def header(buf) peek = buf.getbyte(0) header = {} header[:type], type = HEADREP.find do |_t, desc| mask = (peek >> desc[:prefix]) << desc[:prefix] mask == desc[:pattern] end raise CompressionError unless header[:type] header[:name] = integer(buf, type[:prefix]) case header[:type] when :indexed raise 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 |
#integer(buf, n) ⇒ Integer
Decodes integer value from provided buffer.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/http/2/header/decompressor.rb', line 32 def integer(buf, n) limit = (2**n) - 1 i = n.zero? ? 0 : (shift_byte(buf) & limit) m = 0 if i == limit while (byte = shift_byte(buf)) i += ((byte & 127) << m) m += 7 break if byte.nobits?(128) end end i end |
#string(buf) ⇒ String
Decodes string value from provided buffer.
54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/http/2/header/decompressor.rb', line 54 def string(buf) raise CompressionError, "invalid header block fragment" if buf.empty? huffman = buf.getbyte(0).allbits?(0x80) len = integer(buf, 7) str = read_str(buf, len) raise CompressionError, "string too short" unless str.bytesize == len str = Huffman.new.decode(str) if huffman str.force_encoding(Encoding::UTF_8) end |
#table_size=(size) ⇒ Object
Set dynamic table size in EncodingContext
23 24 25 |
# File 'lib/http/2/header/decompressor.rb', line 23 def table_size=(size) @cc.table_size = size end |