Class: HTTP2::Header::Decompressor
- Inherits:
-
Object
- Object
- HTTP2::Header::Decompressor
- Includes:
- BufferUtils, Error
- Defined in:
- lib/http/2/header/decompressor.rb,
sig/header/decompressor.rbs
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) ⇒ Object
Decodes and processes header commands within provided
buf. -
#header(buf) ⇒ header_command
Decodes header command from provided
buf. -
#initialize(settings = Settings.new) ⇒ 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
buf. -
#table_size=(size) ⇒ void
Set dynamic table
sizein EncodingContext.
Methods included from BufferUtils
#append_str, #read_str, #read_uint32, #shift_byte
Methods included from Error
Constructor Details
#initialize(settings = Settings.new) ⇒ Decompressor
Returns a new instance of Decompressor.
14 15 16 |
# File 'lib/http/2/header/decompressor.rb', line 14 def initialize(settings = Settings.new) @cc = EncodingContext.new(settings) end |
Instance Method Details
#decode(arg0, arg1) ⇒ Array[header_pair] #decode(arg0) ⇒ Array[header_pair]
Decodes and processes header commands within provided buf.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/http/2/header/decompressor.rb', line 98 def decode(buf, frame = nil) list = [] #: Array[header_pair] 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) ⇒ header_command
Decodes header command from provided buf.
64 65 66 67 68 69 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 |
# File 'lib/http/2/header/decompressor.rb', line 64 def header(buf) peek = buf.getbyte(0) header_type, type = HEADREP.find do |_, desc| mask = (peek >> desc[:prefix]) << desc[:prefix] mask == desc[:pattern] end raise CompressionError unless header_type && type header_name = integer(buf, type[:prefix]) case header_type when :indexed raise CompressionError if header_name.zero? header_name -= 1 { type: header_type, name: header_name } when :changetablesize { type: header_type, name: header_name, value: header_name } else if header_name.zero? header_name = string(buf) else header_name -= 1 end header_value = string(buf) { type: header_type, name: header_name, value: header_value } end end |
#integer(buf, n) ⇒ Integer
Decodes integer value from provided buffer.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/http/2/header/decompressor.rb', line 24 def integer(buf, n) limit = (1 << n) - 1 if n.zero? i = 0 consumed = 0 else i = buf.getbyte(0) & limit consumed = 1 end if i == limit m = 0 while (byte = buf.getbyte(consumed)) i += ((byte & 127) << m) m += 7 consumed += 1 break if byte.nobits?(128) end end read_str(buf, consumed) i end |
#string(buf) ⇒ String
Decodes string value from provided buf.
raises CompressionError when input is malformed
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/http/2/header/decompressor.rb', line 51 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.decode(str) if huffman str.force_encoding(Encoding::UTF_8) end |
#table_size=(size) ⇒ void
This method returns an undefined value.
Set dynamic table size in EncodingContext
19 20 21 |
# File 'lib/http/2/header/decompressor.rb', line 19 def table_size=(size) @cc.table_size = size end |