websocket 1.2.4 → 1.2.5

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 (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'