websocket 1.2.4 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +16 -0
  3. data/.rubocop.yml +18 -3
  4. data/.travis.yml +6 -8
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +10 -0
  7. data/README.md +2 -2
  8. data/Rakefile +1 -1
  9. data/lib/websocket.rb +1 -0
  10. data/lib/websocket/frame/base.rb +1 -7
  11. data/lib/websocket/frame/handler/base.rb +2 -2
  12. data/lib/websocket/frame/handler/handler03.rb +2 -1
  13. data/lib/websocket/frame/handler/handler75.rb +1 -1
  14. data/lib/websocket/handshake/base.rb +1 -7
  15. data/lib/websocket/handshake/handler/client.rb +9 -0
  16. data/lib/websocket/handshake/handler/client04.rb +6 -7
  17. data/lib/websocket/handshake/handler/client75.rb +6 -7
  18. data/lib/websocket/handshake/handler/client76.rb +2 -7
  19. data/lib/websocket/handshake/handler/server75.rb +13 -5
  20. data/lib/websocket/handshake/handler/server76.rb +9 -17
  21. data/lib/websocket/handshake/server.rb +1 -1
  22. data/lib/websocket/nice_inspect.rb +10 -0
  23. data/lib/websocket/version.rb +1 -1
  24. data/spec/frame/incoming_03_spec.rb +3 -2
  25. data/spec/frame/incoming_04_spec.rb +3 -2
  26. data/spec/frame/incoming_05_spec.rb +3 -2
  27. data/spec/frame/incoming_07_spec.rb +3 -2
  28. data/spec/frame/incoming_75_spec.rb +3 -2
  29. data/spec/frame/incoming_common_spec.rb +17 -8
  30. data/spec/frame/masking_spec.rb +2 -1
  31. data/spec/frame/outgoing_03_spec.rb +2 -1
  32. data/spec/frame/outgoing_04_spec.rb +2 -1
  33. data/spec/frame/outgoing_05_spec.rb +2 -1
  34. data/spec/frame/outgoing_07_spec.rb +2 -1
  35. data/spec/frame/outgoing_75_spec.rb +2 -1
  36. data/spec/frame/outgoing_common_spec.rb +10 -4
  37. data/spec/handshake/client_04_spec.rb +3 -3
  38. data/spec/handshake/client_11_spec.rb +2 -2
  39. data/spec/handshake/client_75_spec.rb +1 -1
  40. data/spec/handshake/client_76_spec.rb +3 -3
  41. data/spec/handshake/server_04_spec.rb +2 -2
  42. data/spec/handshake/server_76_spec.rb +8 -8
  43. data/spec/spec_helper.rb +0 -2
  44. data/spec/support/all_client_drafts.rb +21 -21
  45. data/spec/support/all_server_drafts.rb +19 -16
  46. data/spec/support/incoming_frames.rb +29 -12
  47. data/spec/support/outgoing_frames.rb +28 -8
  48. data/websocket.gemspec +2 -4
  49. metadata +7 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bf1d6b28aadb7224c53978094d179673364550a
4
- data.tar.gz: 0d376d27450259b680f585c8ff9dc56a7d3e5210
3
+ metadata.gz: d1beb710905d152c983423d7119156b054b515c3
4
+ data.tar.gz: e74c5149d1ff19ff7b5ed25a499c0d2b2d3bef4b
5
5
  SHA512:
6
- metadata.gz: 0ab8110e8e84a36c606da58933b48b89e9df724dc145b4ac4d7cbe36f51c6c56f02ece9ad077103be2fba3d4c617c19692f0a2e1934037a39bf50bb47c81c6c1
7
- data.tar.gz: 7239ff151df05fb67c67a713c6485377a1e0ab13446a945cef84497979aab255c18a09eaa794cc068da59e44d9f7f536af6d8bfe8dc75cd8fa3d70d1b9f43dcf
6
+ metadata.gz: 2ec8c925807edd84216c70bfdc7947f9d24c5f37d9ca4eb11274f8f32d99bd0e405b7fe3ad405d1ad835318a18ef9aaf0256bf4d0996ef6bedbdf89455b2b6e0
7
+ data.tar.gz: 8a64ac2c2bb7da84c15afe43df803abc14d90a6d7e65d358f7a52b909c663a2fab1641c14e0d2666ed5d712f2e6c0bae97dd1ce31818fd48dbde77184bf7e855
@@ -0,0 +1,16 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ fixme:
9
+ enabled: true
10
+ rubocop:
11
+ enabled: true
12
+ ratings:
13
+ paths:
14
+ - "**.rb"
15
+ exclude_paths:
16
+ - spec/
@@ -1,5 +1,8 @@
1
+ require: rubocop-rspec
2
+
1
3
  AllCops:
2
4
  DisplayCopNames: true
5
+ TargetRubyVersion: 2.1
3
6
 
4
7
  # Target: 15
5
8
  Metrics/AbcSize:
@@ -37,8 +40,20 @@ Metrics/PerceivedComplexity:
37
40
  - lib/websocket/frame/handler/handler75.rb
38
41
  - spec/support/handshake_requests.rb
39
42
 
40
- Style/Documentation:
43
+ RSpec/DescribeClass:
44
+ Enabled: false
45
+
46
+ RSpec/ExampleLength:
47
+ Enabled: false
48
+
49
+ RSpec/InstanceVariable:
41
50
  Enabled: false
42
51
 
43
- Style/TrivialAccessors:
44
- AllowPredicates: true
52
+ RSpec/MultipleExpectations:
53
+ Enabled: false
54
+
55
+ RSpec/NamedSubject:
56
+ Enabled: false
57
+
58
+ Style/Documentation:
59
+ Enabled: false
@@ -1,23 +1,21 @@
1
+ dist: trusty
1
2
  language: ruby
2
3
  script: "bundle exec rake"
3
4
  rvm:
4
- - 1.9.3
5
- - 2.0
6
5
  - 2.1
7
6
  - 2.2
8
7
  - 2.3
8
+ - 2.4
9
9
  - ruby-head
10
- - jruby
10
+ - jruby-9.1.9.0 # https://github.com/travis-ci/travis-ci/issues/8446
11
11
  - jruby-head
12
- - rbx
13
- - rbx-head
12
+ - rbx-3
14
13
 
15
14
  matrix:
16
15
  allow_failures:
17
16
  - rvm: ruby-head
18
17
  - rvm: jruby-head
19
- - rvm: rbx
20
- - rvm: rbx-head
18
+ - rvm: rbx-3
21
19
 
22
20
  before_install:
23
- - gem install bundler
21
+ - gem update bundler
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.5
4
+
5
+ - make handshake server resilient to non-string Rack env keys
6
+
3
7
  ## 1.2.4
4
8
 
5
9
  - add subprotocol handling for both server and client
data/Gemfile CHANGED
@@ -1,3 +1,13 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
+ group :development do
4
+ gem 'rake'
5
+ gem 'rspec', '~> 3.0'
6
+
7
+ # Use same version as Code Climate for consistency with CI
8
+ # https://github.com/codeclimate/codeclimate-rubocop/blob/master/Gemfile.lock
9
+ gem 'rubocop', '0.46.0', require: false
10
+ gem 'rubocop-rspec', '1.8.0', require: false
11
+ end
12
+
3
13
  gemspec
data/README.md CHANGED
@@ -4,8 +4,8 @@ Universal Ruby library to handle WebSocket protocol. It focuses on providing abs
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/websocket.svg)](http://badge.fury.io/rb/websocket)
6
6
  [![Gem Downloads](https://img.shields.io/gem/dt/websocket.svg?maxAge=2592000)](https://rubygems.org/gems/websocket)
7
- [![Travis CI](https://travis-ci.org/imanel/websocket-ruby.png)](http://travis-ci.org/imanel/websocket-ruby)
8
- [![Code Climate](https://codeclimate.com/github/imanel/websocket-ruby.png)](https://codeclimate.com/github/imanel/websocket-ruby)
7
+ [![Travis CI](https://travis-ci.org/imanel/websocket-ruby.svg)](http://travis-ci.org/imanel/websocket-ruby)
8
+ [![Code Climate](https://codeclimate.com/github/imanel/websocket-ruby.svg)](https://codeclimate.com/github/imanel/websocket-ruby)
9
9
 
10
10
  **Autobahn tests:** [server](http://imanel.github.com/websocket-ruby/autobahn/server/), [client](http://imanel.github.com/websocket-ruby/autobahn/client/)
11
11
 
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ end
11
11
 
12
12
  RuboCop::RakeTask.new
13
13
 
14
- task default: [:spec, :rubocop]
14
+ task default: %i(spec rubocop)
15
15
 
16
16
  namespace :autobahn do
17
17
  desc 'Run autobahn tests for client'
@@ -12,6 +12,7 @@ module WebSocket
12
12
  autoload :ExceptionHandler, "#{ROOT}/websocket/exception_handler"
13
13
  autoload :Frame, "#{ROOT}/websocket/frame"
14
14
  autoload :Handshake, "#{ROOT}/websocket/handshake"
15
+ autoload :NiceInspect, "#{ROOT}/websocket/nice_inspect"
15
16
 
16
17
  # Limit of frame size payload in bytes
17
18
  def self.max_frame_size
@@ -3,6 +3,7 @@ module WebSocket
3
3
  # @abstract Subclass and override to implement custom frames
4
4
  class Base
5
5
  include ExceptionHandler
6
+ include NiceInspect
6
7
 
7
8
  attr_reader :type, :version, :error
8
9
  attr_accessor :data, :code
@@ -39,13 +40,6 @@ module WebSocket
39
40
  raise NotImplementedError
40
41
  end
41
42
 
42
- # Recreate inspect as #to_s was overwritten
43
- def inspect
44
- vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
45
- insp = Kernel.format("#{self.class}:0x%08x", __id__)
46
- "<#{insp} #{vars}>"
47
- end
48
-
49
43
  private
50
44
 
51
45
  # Include set of methods for selected protocol version
@@ -24,14 +24,14 @@ module WebSocket
24
24
  # @param [Symbol] frame_type Frame type
25
25
  # @return [Boolean] True if given frame type is control frame
26
26
  def control_frame?(frame_type)
27
- ![:text, :binary, :continuation].include?(frame_type)
27
+ !%i(text binary continuation).include?(frame_type)
28
28
  end
29
29
 
30
30
  # Check if frame is one of data frames
31
31
  # @param [Symbol] frame_type Frame type
32
32
  # @return [Boolean] True if given frame type is data frame
33
33
  def data_frame?(frame_type)
34
- [:text, :binary].include?(frame_type)
34
+ %i(text binary).include?(frame_type)
35
35
  end
36
36
  end
37
37
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: binary
2
+
2
3
  require 'securerandom'
3
4
 
4
5
  module WebSocket
@@ -20,7 +21,7 @@ module WebSocket
20
21
 
21
22
  # @see WebSocket::Frame::Base#supported_frames
22
23
  def supported_frames
23
- [:text, :binary, :close, :ping, :pong]
24
+ %i(text binary close ping pong)
24
25
  end
25
26
 
26
27
  # @see WebSocket::Frame::Handler::Base#encode_frame
@@ -6,7 +6,7 @@ module WebSocket
6
6
  class Handler75 < Base
7
7
  # @see WebSocket::Frame::Base#supported_frames
8
8
  def supported_frames
9
- [:text, :close]
9
+ %i(text close)
10
10
  end
11
11
 
12
12
  # @see WebSocket::Frame::Handler::Base#encode_frame
@@ -3,6 +3,7 @@ module WebSocket
3
3
  # @abstract Subclass and override to implement custom handshakes
4
4
  class Base
5
5
  include ExceptionHandler
6
+ include NiceInspect
6
7
 
7
8
  attr_reader :host, :port, :path, :query,
8
9
  :state, :version, :secure,
@@ -32,13 +33,6 @@ module WebSocket
32
33
  end
33
34
  rescue_method :to_s, return: ''
34
35
 
35
- # Recreate inspect as #to_s was overwritten
36
- def inspect
37
- vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
38
- insp = Kernel.format("#{self.class}:0x%08x", __id__)
39
- "<#{insp} #{vars}>"
40
- end
41
-
42
36
  # Is parsing of data finished?
43
37
  # @return [Boolena] True if request was completely parsed or error occured. False otherwise
44
38
  def finished?
@@ -15,6 +15,15 @@ module WebSocket
15
15
  def handshake_keys
16
16
  super + @handshake.headers.to_a
17
17
  end
18
+
19
+ # Verify if received header matches with one of the sent ones
20
+ # @return [Boolean] True if matching. False otherwise(appropriate error is set)
21
+ def verify_protocol
22
+ return true if supported_protocols.empty?
23
+ protos = provided_protocols & supported_protocols
24
+ raise WebSocket::Error::Handshake::UnsupportedProtocol if protos.empty?
25
+ true
26
+ end
18
27
  end
19
28
  end
20
29
  end
@@ -48,13 +48,12 @@ module WebSocket
48
48
  true
49
49
  end
50
50
 
51
- # Verify if received header Sec-WebSocket-Protocol matches with one of the sent ones
52
- # @return [Boolean] True if matching. False otherwise(appropriate error is set)
53
- def verify_protocol
54
- return true if @handshake.protocols.empty?
55
- protos = @handshake.headers['sec-websocket-protocol'].split(/ *, */) & @handshake.protocols
56
- raise WebSocket::Error::Handshake::UnsupportedProtocol if protos.empty?
57
- true
51
+ def supported_protocols
52
+ @handshake.protocols
53
+ end
54
+
55
+ def provided_protocols
56
+ @handshake.headers['sec-websocket-protocol'].to_s.split(/ *, */)
58
57
  end
59
58
  end
60
59
  end
@@ -24,13 +24,12 @@ module WebSocket
24
24
  keys
25
25
  end
26
26
 
27
- # Verify if received header WebSocket-Protocol matches with the sent one
28
- # @return [Boolean] True if matching. False otherwise(appropriate error is set)
29
- def verify_protocol
30
- return true if @handshake.protocols.empty?
31
- invalid = @handshake.headers['websocket-protocol'].strip != @handshake.protocols.first
32
- raise WebSocket::Error::Handshake::UnsupportedProtocol if invalid
33
- true
27
+ def supported_protocols
28
+ Array(@handshake.protocols.first)
29
+ end
30
+
31
+ def provided_protocols
32
+ Array(@handshake.headers['websocket-protocol'].to_s.strip)
34
33
  end
35
34
  end
36
35
  end
@@ -94,13 +94,8 @@ module WebSocket
94
94
  [rand(0x100000000)].pack('N') + [rand(0x100000000)].pack('N')
95
95
  end
96
96
 
97
- # Verify if received header Sec-WebSocket-Protocol matches with the sent one
98
- # @return [Boolean] True if matching. False otherwise(appropriate error is set)
99
- def verify_protocol
100
- return true if @handshake.protocols.empty?
101
- invalid = @handshake.headers['sec-websocket-protocol'].strip != @handshake.protocols.first
102
- raise WebSocket::Error::Handshake::UnsupportedProtocol if invalid
103
- true
97
+ def provided_protocols
98
+ Array(@handshake.headers['sec-websocket-protocol'].to_s.strip)
104
99
  end
105
100
  end
106
101
  end
@@ -4,6 +4,14 @@ module WebSocket
4
4
  class Server75 < Server
5
5
  private
6
6
 
7
+ def headers
8
+ {
9
+ origin: 'WebSocket-Origin',
10
+ location: 'WebSocket-Location',
11
+ protocol: 'WebSocket-Protocol'
12
+ }.freeze
13
+ end
14
+
7
15
  # @see WebSocket::Handshake::Handler::Base#header_line
8
16
  def header_line
9
17
  'HTTP/1.1 101 Web Socket Protocol Handshake'
@@ -14,15 +22,15 @@ module WebSocket
14
22
  [
15
23
  %w(Upgrade WebSocket),
16
24
  %w(Connection Upgrade),
17
- ['WebSocket-Origin', @handshake.headers['origin']],
18
- ['WebSocket-Location', @handshake.uri]
25
+ [headers[:origin], @handshake.headers['origin']],
26
+ [headers[:location], @handshake.uri]
19
27
  ] + protocol
20
28
  end
21
29
 
22
30
  def protocol
23
- return [] unless @handshake.headers.key?('websocket-protocol')
24
- proto = @handshake.headers['websocket-protocol']
25
- [['WebSocket-Protocol', @handshake.protocols.include?(proto) ? proto : nil]]
31
+ return [] unless @handshake.headers.key?(headers[:protocol].downcase)
32
+ proto = @handshake.headers[headers[:protocol].downcase]
33
+ [[headers[:protocol], @handshake.protocols.include?(proto) ? proto : nil]]
26
34
  end
27
35
  end
28
36
  end
@@ -3,7 +3,7 @@ require 'digest/md5'
3
3
  module WebSocket
4
4
  module Handshake
5
5
  module Handler
6
- class Server76 < Server
6
+ class Server76 < Server75
7
7
  # @see WebSocket::Handshake::Base#valid?
8
8
  def valid?
9
9
  super && !finishing_line.nil?
@@ -11,6 +11,14 @@ module WebSocket
11
11
 
12
12
  private
13
13
 
14
+ def headers
15
+ {
16
+ origin: 'Sec-WebSocket-Origin',
17
+ location: 'Sec-WebSocket-Location',
18
+ protocol: 'Sec-WebSocket-Protocol'
19
+ }.freeze
20
+ end
21
+
14
22
  # @see WebSocket::Handshake::Base#reserved_leftover_lines
15
23
  def reserved_leftover_lines
16
24
  1
@@ -21,16 +29,6 @@ module WebSocket
21
29
  'HTTP/1.1 101 WebSocket Protocol Handshake'
22
30
  end
23
31
 
24
- # @see WebSocket::Handshake::Handler::Base#handshake_keys
25
- def handshake_keys
26
- [
27
- %w(Upgrade WebSocket),
28
- %w(Connection Upgrade),
29
- ['Sec-WebSocket-Origin', @handshake.headers['origin']],
30
- ['Sec-WebSocket-Location', @handshake.uri]
31
- ] + protocol
32
- end
33
-
34
32
  # @see WebSocket::Handshake::Handler::Base#finishing_line
35
33
  def finishing_line
36
34
  @finishing_line ||= challenge_response
@@ -69,12 +67,6 @@ module WebSocket
69
67
 
70
68
  quotient
71
69
  end
72
-
73
- def protocol
74
- return [] unless @handshake.headers.key?('sec-websocket-protocol')
75
- proto = @handshake.headers['sec-websocket-protocol']
76
- [['Sec-WebSocket-Protocol', @handshake.protocols.include?(proto) ? proto : nil]]
77
- end
78
70
  end
79
71
  end
80
72
  end
@@ -71,7 +71,7 @@ module WebSocket
71
71
  # @example
72
72
  # @handshake.from_rack(env)
73
73
  def from_rack(env)
74
- @headers = env.select { |key, _value| key.start_with? 'HTTP_' }.each_with_object({}) do |tuple, memo|
74
+ @headers = env.select { |key, _value| key.to_s.start_with? 'HTTP_' }.each_with_object({}) do |tuple, memo|
75
75
  key, value = tuple
76
76
  memo[key.gsub(/\AHTTP_/, '').tr('_', '-').downcase] = value
77
77
  end
@@ -0,0 +1,10 @@
1
+ module WebSocket
2
+ module NiceInspect
3
+ # Recreate inspect as #to_s will be overwritten
4
+ def inspect
5
+ vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
6
+ insp = Kernel.format("#{self.class}:0x%08x", __id__)
7
+ "<#{insp} #{vars}>"
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module WebSocket
2
- VERSION = '1.2.4'.freeze
2
+ VERSION = '1.2.5'.freeze
3
3
  end
@@ -1,14 +1,15 @@
1
1
  # encoding: binary
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  RSpec.describe 'Incoming frame draft 03' do
6
+ subject { frame }
5
7
  let(:version) { 3 }
6
8
  let(:frame) { WebSocket::Frame::Incoming.new(version: version, data: encoded_text) }
7
9
  let(:encoded_text) { nil }
8
10
  let(:decoded_text) { nil }
9
11
  let(:frame_type) { nil }
10
12
  let(:error) { nil }
11
- subject { frame }
12
13
 
13
14
  it_should_behave_like 'valid_incoming_frame'
14
15
 
@@ -54,7 +55,7 @@ RSpec.describe 'Incoming frame draft 03' do
54
55
 
55
56
  context 'should properly decode text frame in between of continuation' do
56
57
  let(:encoded_text) { "\x84\x03Hel\x03\x03abc\x00\x02lo" }
57
- let(:frame_type) { [:pong, :text] }
58
+ let(:frame_type) { %i(pong text) }
58
59
  let(:decoded_text) { %w(abc Hello) }
59
60
 
60
61
  it_should_behave_like 'valid_incoming_frame'