http-2 0.10.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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