http-2 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -2
  3. data/lib/http/2/buffer.rb +6 -4
  4. data/lib/http/2/client.rb +5 -1
  5. data/lib/http/2/compressor.rb +44 -36
  6. data/lib/http/2/connection.rb +76 -89
  7. data/lib/http/2/emitter.rb +4 -1
  8. data/lib/http/2/error.rb +2 -0
  9. data/lib/http/2/flow_buffer.rb +8 -3
  10. data/lib/http/2/framer.rb +83 -94
  11. data/lib/http/2/huffman.rb +19 -17
  12. data/lib/http/2/server.rb +9 -7
  13. data/lib/http/2/stream.rb +48 -48
  14. data/lib/http/2/version.rb +3 -1
  15. data/lib/http/2.rb +2 -0
  16. metadata +10 -63
  17. data/.autotest +0 -20
  18. data/.coveralls.yml +0 -1
  19. data/.gitignore +0 -20
  20. data/.gitmodules +0 -3
  21. data/.rspec +0 -5
  22. data/.rubocop.yml +0 -93
  23. data/.rubocop_todo.yml +0 -122
  24. data/.travis.yml +0 -14
  25. data/Gemfile +0 -16
  26. data/Guardfile +0 -18
  27. data/Guardfile.h2spec +0 -12
  28. data/Rakefile +0 -49
  29. data/example/Gemfile +0 -3
  30. data/example/README.md +0 -44
  31. data/example/client.rb +0 -122
  32. data/example/helper.rb +0 -19
  33. data/example/keys/server.crt +0 -20
  34. data/example/keys/server.key +0 -27
  35. data/example/server.rb +0 -139
  36. data/example/upgrade_client.rb +0 -153
  37. data/example/upgrade_server.rb +0 -203
  38. data/http-2.gemspec +0 -22
  39. data/lib/tasks/generate_huffman_table.rb +0 -166
  40. data/spec/buffer_spec.rb +0 -28
  41. data/spec/client_spec.rb +0 -188
  42. data/spec/compressor_spec.rb +0 -666
  43. data/spec/connection_spec.rb +0 -665
  44. data/spec/emitter_spec.rb +0 -54
  45. data/spec/framer_spec.rb +0 -487
  46. data/spec/h2spec/h2spec.darwin +0 -0
  47. data/spec/h2spec/output/non_secure.txt +0 -317
  48. data/spec/helper.rb +0 -147
  49. data/spec/hpack_test_spec.rb +0 -84
  50. data/spec/huffman_spec.rb +0 -68
  51. data/spec/server_spec.rb +0 -52
  52. data/spec/stream_spec.rb +0 -878
  53. data/spec/support/deep_dup.rb +0 -55
  54. data/spec/support/duplicable.rb +0 -98
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dd78ba6a3468b6a3ceda2ebabc37ceb895a90d675d9fecc035b74d2f479a457
4
- data.tar.gz: d70542d69e57050ab9ee3c837b6123fea81424a03bf3b99ffdc889a54a2fd20c
3
+ metadata.gz: d1788e5559bb1f36b98896322d1c846ef73b0fba4a7a45b524845735deacb9aa
4
+ data.tar.gz: 62ea957139ea576aa4553303f6db141cd9297a8ce75624553e79a90a69f74717
5
5
  SHA512:
6
- metadata.gz: f678316f6235ed93ce5a3902ef3bf4c48854605de0875054d1f3e05196fc161bdfe49d149ff930413bef5ca76c61ab2d193092867a383f1f5dbe309cfef0f012
7
- data.tar.gz: 52fce71379a9299df1cd8c93d44964d668d09c199564482193513b109a6339f220b4ae1e724c5965892b3e53855820a810e95405b8eb198797ea130611d39a05
6
+ metadata.gz: fb252eeff936187cf2ebebdf93e69fb6f82dba50a0fece880f40a8235b790165ad5d3f167b0c3948adf040388fc7cd49bc1bd1a24b754447c83dd2020be78eaa
7
+ data.tar.gz: 0657b1b61f526041167473faf29e50a0cbf4bbfcbac80a458a98a205ab5a01f409da7d62010e5620e5e5fe6cb6e7d1bd5a2ae2a831fcac7da1c1ab2192511c1e
data/README.md CHANGED
@@ -1,9 +1,7 @@
1
1
  # HTTP-2
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/http-2.svg)](http://rubygems.org/gems/http-2)
4
- [![Build Status](https://travis-ci.org/igrigorik/http-2.svg?branch=master)](https://travis-ci.org/igrigorik/http-2)
5
4
  [![Coverage Status](https://coveralls.io/repos/igrigorik/http-2/badge.svg)](https://coveralls.io/r/igrigorik/http-2)
6
- [![Analytics](https://ga-beacon.appspot.com/UA-71196-10/http-2/readme)](https://github.com/igrigorik/ga-beacon)
7
5
 
8
6
  Pure Ruby, framework and transport agnostic, implementation of HTTP/2 protocol and HPACK header compression with support for:
9
7
 
data/lib/http/2/buffer.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
 
3
5
  module HTTP2
@@ -6,11 +8,11 @@ module HTTP2
6
8
  class Buffer
7
9
  extend Forwardable
8
10
 
9
- def_delegators :@buffer, :ord, :encoding, :setbyte, :unpack,
11
+ def_delegators :@buffer, :ord, :encoding, :setbyte, :unpack, :unpack1,
10
12
  :size, :each_byte, :to_str, :to_s, :length, :inspect,
11
13
  :[], :[]=, :empty?, :bytesize, :include?
12
14
 
13
- UINT32 = 'N'.freeze
15
+ UINT32 = 'N'
14
16
  private_constant :UINT32
15
17
 
16
18
  # Forces binary encoding on the string
@@ -59,12 +61,12 @@ module HTTP2
59
61
  # Slice unsigned 32-bit integer from buffer.
60
62
  # @return [Integer]
61
63
  def read_uint32
62
- read(4).unpack(UINT32).first
64
+ read(4).unpack1(UINT32)
63
65
  end
64
66
 
65
67
  # Ensures that data that is added is binary encoded as well,
66
68
  # otherwise this could lead to the Buffer instance changing its encoding.
67
- [:<<, :prepend].each do |mutating_method|
69
+ %i[<< prepend].each do |mutating_method|
68
70
  define_method(mutating_method) do |string|
69
71
  string = string.dup if string.frozen?
70
72
  @buffer.send mutating_method, string.force_encoding(Encoding::BINARY)
data/lib/http/2/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTTP2
2
4
  # HTTP 2.0 client connection class that implements appropriate header
3
5
  # compression / decompression algorithms and stream management logic.
@@ -45,7 +47,8 @@ module HTTP2
45
47
 
46
48
  # sends the preface and initializes the first stream in half-closed state
47
49
  def upgrade
48
- fail ProtocolError unless @stream_id == 1
50
+ raise ProtocolError unless @stream_id == 1
51
+
49
52
  send_connection_preface
50
53
  new_stream(state: :half_closed_local)
51
54
  end
@@ -53,6 +56,7 @@ module HTTP2
53
56
  # Emit the connection preface if not yet
54
57
  def send_connection_preface
55
58
  return unless @state == :waiting_connection_preface
59
+
56
60
  @state = :connected
57
61
  emit(:frame, CONNECTION_PREFACE_MAGIC)
58
62
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTTP2
2
4
  # Implementation of header compression for HTTP 2.0 (HPACK) format adapted
3
5
  # to efficiently represent HTTP headers in the context of HTTP 2.0.
@@ -74,7 +76,7 @@ module HTTP2
74
76
  ['user-agent', ''],
75
77
  ['vary', ''],
76
78
  ['via', ''],
77
- ['www-authenticate', ''],
79
+ ['www-authenticate', '']
78
80
  ].each { |pair| pair.each(&:freeze).freeze }.freeze
79
81
 
80
82
  # Current table of header key-value pairs.
@@ -96,9 +98,9 @@ module HTTP2
96
98
  # :index Symbol :all, :static, :never
97
99
  def initialize(**options)
98
100
  default_options = {
99
- huffman: :shorter,
100
- index: :all,
101
- table_size: 4096,
101
+ huffman: :shorter,
102
+ index: :all,
103
+ table_size: 4096
102
104
  }
103
105
  @table = []
104
106
  @options = default_options.merge(options)
@@ -112,7 +114,7 @@ module HTTP2
112
114
  t = @table
113
115
  l = @limit
114
116
  other.instance_eval do
115
- @table = t.dup # shallow copy
117
+ @table = t.dup # shallow copy
116
118
  @limit = l
117
119
  end
118
120
  other
@@ -131,7 +133,8 @@ module HTTP2
131
133
  def dereference(index)
132
134
  # NOTE: index is zero-based in this module.
133
135
  value = STATIC_TABLE[index] || @table[index - STATIC_TABLE.size]
134
- fail CompressionError, 'Index too large' unless value
136
+ raise CompressionError, 'Index too large' unless value
137
+
135
138
  value
136
139
  end
137
140
 
@@ -146,9 +149,8 @@ module HTTP2
146
149
 
147
150
  case cmd[:type]
148
151
  when :changetablesize
149
- if cmd[:value] > @limit
150
- fail CompressionError, 'dynamic table size update exceed limit'
151
- end
152
+ raise CompressionError, 'dynamic table size update exceed limit' if cmd[:value] > @limit
153
+
152
154
  self.table_size = cmd[:value]
153
155
 
154
156
  when :indexed
@@ -186,7 +188,7 @@ module HTTP2
186
188
  add_to_table(emit) if cmd[:type] == :incremental
187
189
 
188
190
  else
189
- fail CompressionError, "Invalid type: #{cmd[:type]}"
191
+ raise CompressionError, "Invalid type: #{cmd[:type]}"
190
192
  end
191
193
 
192
194
  emit
@@ -202,7 +204,7 @@ module HTTP2
202
204
  def encode(headers)
203
205
  commands = []
204
206
  # Literals commands are marked with :noindex when index is not used
205
- noindex = [:static, :never].include?(@options[:index])
207
+ noindex = %i[static never].include?(@options[:index])
206
208
  headers.each do |field, value|
207
209
  # Literal header names MUST be translated to lowercase before
208
210
  # encoding and transmission.
@@ -232,7 +234,7 @@ module HTTP2
232
234
  exact = nil
233
235
  name_only = nil
234
236
 
235
- if [:all, :static].include?(@options[:index])
237
+ if %i[all static].include?(@options[:index])
236
238
  STATIC_TABLE.each_index do |i|
237
239
  if STATIC_TABLE[i] == header
238
240
  exact ||= i
@@ -284,6 +286,7 @@ module HTTP2
284
286
  # @param cmd [Array] +[name, value]+
285
287
  def add_to_table(cmd)
286
288
  return unless size_check(cmd)
289
+
287
290
  @table.unshift(cmd)
288
291
  end
289
292
 
@@ -309,11 +312,11 @@ module HTTP2
309
312
 
310
313
  # Header representation as defined by the spec.
311
314
  HEADREP = {
312
- indexed: { prefix: 7, pattern: 0x80 },
313
- incremental: { prefix: 6, pattern: 0x40 },
314
- noindex: { prefix: 4, pattern: 0x00 },
315
+ indexed: { prefix: 7, pattern: 0x80 },
316
+ incremental: { prefix: 6, pattern: 0x40 },
317
+ noindex: { prefix: 4, pattern: 0x00 },
315
318
  neverindexed: { prefix: 4, pattern: 0x10 },
316
- changetablesize: { prefix: 5, pattern: 0x20 },
319
+ changetablesize: { prefix: 5, pattern: 0x20 }
317
320
  }.each_value(&:freeze).freeze
318
321
 
319
322
  # Predefined options set for Compressor
@@ -330,8 +333,9 @@ module HTTP2
330
333
  # Responsible for encoding header key-value pairs using HPACK algorithm.
331
334
  class Compressor
332
335
  # @param options [Hash] encoding options
336
+ # @see EncodingContext#initialize
333
337
  def initialize(**options)
334
- @cc = EncodingContext.new(options)
338
+ @cc = EncodingContext.new(**options)
335
339
  end
336
340
 
337
341
  # Set dynamic table size in EncodingContext
@@ -356,14 +360,14 @@ module HTTP2
356
360
  # @param n [Integer] number of available bits
357
361
  # @return [String] binary string
358
362
  def integer(i, n)
359
- limit = 2**n - 1
363
+ limit = (2**n) - 1
360
364
  return [i].pack('C') if i < limit
361
365
 
362
366
  bytes = []
363
367
  bytes.push limit unless n.zero?
364
368
 
365
369
  i -= limit
366
- while (i >= 128)
370
+ while i >= 128
367
371
  bytes.push((i % 128) + 128)
368
372
  i /= 128
369
373
  end
@@ -393,7 +397,8 @@ module HTTP2
393
397
  # @param str [String]
394
398
  # @return [String] binary string
395
399
  def string(str)
396
- plain, huffman = nil, nil
400
+ plain = nil
401
+ huffman = nil
397
402
  unless @cc.options[:huffman] == :always
398
403
  plain = integer(str.bytesize, 7) << str.dup.force_encoding(Encoding::BINARY)
399
404
  end
@@ -463,14 +468,11 @@ module HTTP2
463
468
  # Responsible for decoding received headers and maintaining compression
464
469
  # context of the opposing peer. Decompressor must be initialized with
465
470
  # appropriate starting context based on local role: client or server.
466
- #
467
- # @example
468
- # server_role = Decompressor.new(:request)
469
- # client_role = Decompressor.new(:response)
470
471
  class Decompressor
471
472
  # @param options [Hash] decoding options. Only :table_size is effective.
473
+ # @see EncodingContext#initialize
472
474
  def initialize(**options)
473
- @cc = EncodingContext.new(options)
475
+ @cc = EncodingContext.new(**options)
474
476
  end
475
477
 
476
478
  # Set dynamic table size in EncodingContext
@@ -485,16 +487,18 @@ module HTTP2
485
487
  # @param n [Integer] number of available bits
486
488
  # @return [Integer]
487
489
  def integer(buf, n)
488
- limit = 2**n - 1
489
- i = !n.zero? ? (buf.getbyte & limit) : 0
490
+ limit = (2**n) - 1
491
+ i = n.zero? ? 0 : (buf.getbyte & limit)
490
492
 
491
493
  m = 0
492
- while (byte = buf.getbyte)
493
- i += ((byte & 127) << m)
494
- m += 7
494
+ if i == limit
495
+ while (byte = buf.getbyte)
496
+ i += ((byte & 127) << m)
497
+ m += 7
495
498
 
496
- break if (byte & 128).zero?
497
- end if (i == limit)
499
+ break if (byte & 128).zero?
500
+ end
501
+ end
498
502
 
499
503
  i
500
504
  end
@@ -508,7 +512,8 @@ module HTTP2
508
512
  huffman = (buf.readbyte(0) & 0x80) == 0x80
509
513
  len = integer(buf, 7)
510
514
  str = buf.read(len)
511
- fail CompressionError, 'string too short' unless str.bytesize == len
515
+ raise CompressionError, 'string too short' unless str.bytesize == len
516
+
512
517
  str = Huffman.new.decode(Buffer.new(str)) if huffman
513
518
  str.force_encoding(Encoding::UTF_8)
514
519
  end
@@ -526,13 +531,14 @@ module HTTP2
526
531
  mask == desc[:pattern]
527
532
  end
528
533
 
529
- fail CompressionError unless header[:type]
534
+ raise CompressionError unless header[:type]
530
535
 
531
536
  header[:name] = integer(buf, type[:prefix])
532
537
 
533
538
  case header[:type]
534
539
  when :indexed
535
- fail CompressionError if (header[:name]).zero?
540
+ raise CompressionError if (header[:name]).zero?
541
+
536
542
  header[:name] -= 1
537
543
  when :changetablesize
538
544
  header[:value] = header[:name]
@@ -558,10 +564,12 @@ module HTTP2
558
564
  until buf.empty?
559
565
  next_header = @cc.process(header(buf))
560
566
  next if next_header.nil?
567
+
561
568
  is_pseudo_header = next_header.first.start_with? ':'
562
569
  if !decoding_pseudo_headers && is_pseudo_header
563
- fail ProtocolError, 'one or more pseudo headers encountered after regular headers'
570
+ raise ProtocolError, 'one or more pseudo headers encountered after regular headers'
564
571
  end
572
+
565
573
  decoding_pseudo_headers = is_pseudo_header
566
574
  list << next_header
567
575
  end