websocket 1.1.4 → 1.2.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.
- data/.travis.yml +2 -6
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -1
- data/README.md +10 -6
- data/Rakefile +1 -1
- data/lib/websocket.rb +1 -1
- data/lib/websocket/exception_handler.rb +6 -0
- data/lib/websocket/frame/base.rb +1 -1
- data/lib/websocket/frame/data.rb +11 -9
- data/lib/websocket/frame/handler.rb +1 -1
- data/lib/websocket/frame/handler/handler03.rb +17 -17
- data/lib/websocket/frame/handler/handler07.rb +8 -8
- data/lib/websocket/frame/handler/handler75.rb +8 -7
- data/lib/websocket/frame/incoming.rb +1 -1
- data/lib/websocket/frame/outgoing.rb +1 -1
- data/lib/websocket/handshake/base.rb +7 -7
- data/lib/websocket/handshake/client.rb +5 -3
- data/lib/websocket/handshake/handler/base.rb +5 -5
- data/lib/websocket/handshake/handler/client.rb +6 -1
- data/lib/websocket/handshake/handler/client04.rb +7 -6
- data/lib/websocket/handshake/handler/client75.rb +5 -4
- data/lib/websocket/handshake/handler/client76.rb +5 -5
- data/lib/websocket/handshake/handler/server04.rb +11 -6
- data/lib/websocket/handshake/handler/server75.rb +5 -5
- data/lib/websocket/handshake/handler/server76.rb +9 -9
- data/lib/websocket/handshake/server.rb +25 -24
- data/lib/websocket/version.rb +1 -1
- data/spec/frame/incoming_03_spec.rb +25 -25
- data/spec/frame/incoming_04_spec.rb +25 -25
- data/spec/frame/incoming_05_spec.rb +29 -29
- data/spec/frame/incoming_07_spec.rb +31 -31
- data/spec/frame/incoming_75_spec.rb +13 -13
- data/spec/frame/incoming_common_spec.rb +12 -13
- data/spec/frame/masking_spec.rb +10 -10
- data/spec/frame/outgoing_03_spec.rb +17 -17
- data/spec/frame/outgoing_04_spec.rb +17 -17
- data/spec/frame/outgoing_05_spec.rb +17 -17
- data/spec/frame/outgoing_07_spec.rb +19 -19
- data/spec/frame/outgoing_75_spec.rb +9 -9
- data/spec/frame/outgoing_common_spec.rb +7 -8
- data/spec/handshake/client_04_spec.rb +9 -9
- data/spec/handshake/client_75_spec.rb +2 -2
- data/spec/handshake/client_76_spec.rb +9 -9
- data/spec/handshake/server_04_spec.rb +5 -5
- data/spec/handshake/server_75_spec.rb +1 -1
- data/spec/handshake/server_76_spec.rb +21 -21
- data/spec/spec_helper.rb +4 -1
- data/spec/support/all_client_drafts.rb +62 -52
- data/spec/support/all_server_drafts.rb +49 -49
- data/spec/support/handshake_requests.rb +16 -16
- data/spec/support/incoming_frames.rb +28 -28
- data/spec/support/outgoing_frames.rb +10 -10
- data/websocket.gemspec +1 -1
- metadata +42 -22
- checksums.yaml +0 -7
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.0
|
4
|
+
|
5
|
+
- Remove support for Ruby 1.8
|
6
|
+
- Add support for sending custom headers for Client
|
7
|
+
- Better detection and handling of draft 76
|
8
|
+
- Multiple small fixes and optimizations
|
9
|
+
|
3
10
|
## 1.1.4
|
4
11
|
|
5
12
|
- verify valid close codes according to spec
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# WebSocket Ruby
|
2
2
|
|
3
|
-
- Travis CI build: [](http://travis-ci.org/imanel/websocket-ruby)
|
4
|
-
- Autobahn tests: [server](http://imanel.github.com/websocket-ruby/autobahn/server/), [client](http://imanel.github.com/websocket-ruby/autobahn/client/)
|
5
|
-
|
6
3
|
Universal Ruby library to handle WebSocket protocol. It focuses on providing abstraction layer over [WebSocket API](http://dev.w3.org/html5/websockets/) instead of providing server or client functionality.
|
7
4
|
|
5
|
+
[](http://badge.fury.io/rb/websocket)
|
6
|
+
[](http://travis-ci.org/imanel/websocket-ruby)
|
7
|
+
[](https://codeclimate.com/github/imanel/websocket-ruby)
|
8
|
+
|
9
|
+
**Autobahn tests:** [server](http://imanel.github.com/websocket-ruby/autobahn/server/), [client](http://imanel.github.com/websocket-ruby/autobahn/client/)
|
10
|
+
|
8
11
|
Currently WebSocket Ruby supports all existing drafts of WebSocket, which include:
|
9
12
|
|
10
13
|
- [hixie-75](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75)
|
@@ -59,13 +62,14 @@ EOF
|
|
59
62
|
## Client handshake
|
60
63
|
|
61
64
|
``` ruby
|
62
|
-
@handshake = WebSocket::Handshake::Client.new(:
|
65
|
+
@handshake = WebSocket::Handshake::Client.new(url: 'ws://example.com', headers: { 'Cookie' => 'SESSIONID=1234' })
|
63
66
|
|
64
67
|
# Create request
|
65
68
|
@handshake.to_s # GET /demo HTTP/1.1
|
66
69
|
# Upgrade: websocket
|
67
70
|
# Connection: Upgrade
|
68
71
|
# Host: example.com
|
72
|
+
# Cookie: SESSIONID=1234
|
69
73
|
# Sec-WebSocket-Origin: http://example.com
|
70
74
|
# Sec-WebSocket-Version: 13
|
71
75
|
# Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
@@ -90,11 +94,11 @@ EOF
|
|
90
94
|
|
91
95
|
``` ruby
|
92
96
|
# Prepare frame for sending
|
93
|
-
frame = WebSocket::Frame::Outgoing::Server.new(:
|
97
|
+
frame = WebSocket::Frame::Outgoing::Server.new(version: @handshake.version, data: "Hello", type: :text)
|
94
98
|
frame.to_s # "\x81\x05\x48\x65\x6c\x6c\x6f"
|
95
99
|
|
96
100
|
# Parse incoming frames
|
97
|
-
frame = WebSocket::Frame::Incoming::Server.new(:
|
101
|
+
frame = WebSocket::Frame::Incoming::Server.new(version: @handshake.version)
|
98
102
|
frame << "\x81\x05\x48\x65\x6c\x6c\x6f\x81\x06\x77\x6f\x72\x6c\x64\x21"
|
99
103
|
frame.next # "Hello"
|
100
104
|
frame.next # "world!""
|
data/Rakefile
CHANGED
data/lib/websocket.rb
CHANGED
@@ -17,6 +17,12 @@ module WebSocket
|
|
17
17
|
|
18
18
|
module ClassMethods
|
19
19
|
|
20
|
+
# Rescue from WebSocket::Error errors.
|
21
|
+
#
|
22
|
+
# @param [String] method_name Name of method that should be wrapped and rescued
|
23
|
+
# @param [Hash] options Options for rescue
|
24
|
+
#
|
25
|
+
# @options options [Any] :return Value that should be returned instead of raised error
|
20
26
|
def rescue_method(method_name, options = {})
|
21
27
|
define_method "#{method_name}_with_rescue" do |*args|
|
22
28
|
begin
|
data/lib/websocket/frame/base.rb
CHANGED
@@ -41,7 +41,7 @@ module WebSocket
|
|
41
41
|
|
42
42
|
# Recreate inspect as #to_s was overwritten
|
43
43
|
def inspect
|
44
|
-
vars = self.instance_variables.map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(
|
44
|
+
vars = self.instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
|
45
45
|
insp = "#{self.class}:0x%08x" % (self.__id__ * 2)
|
46
46
|
"<#{insp} #{vars}>"
|
47
47
|
end
|
data/lib/websocket/frame/data.rb
CHANGED
@@ -3,35 +3,37 @@ module WebSocket
|
|
3
3
|
class Data < String
|
4
4
|
|
5
5
|
def initialize(*args)
|
6
|
-
super
|
6
|
+
super(*convert_args(args))
|
7
7
|
end
|
8
8
|
|
9
9
|
def <<(*args)
|
10
|
-
super
|
10
|
+
super(*convert_args(args))
|
11
11
|
end
|
12
12
|
|
13
|
+
# Convert all arguments to ASCII-8BIT for easier traversing
|
14
|
+
def convert_args(args)
|
15
|
+
args.each { |arg| arg.force_encoding('ASCII-8BIT') }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Extract mask from 4 first bytes according to spec
|
13
19
|
def set_mask
|
14
20
|
raise WebSocket::Error::Frame::MaskTooShort if bytesize < 4
|
15
21
|
@masking_key = self[0..3].bytes.to_a
|
16
22
|
end
|
17
23
|
|
24
|
+
# Remove mask flag - it will still be present in payload
|
18
25
|
def unset_mask
|
19
26
|
@masking_key = nil
|
20
27
|
end
|
21
28
|
|
29
|
+
# Extract `count` bytes starting from `start_index` and unmask it if needed.
|
22
30
|
def getbytes(start_index, count)
|
23
31
|
data = self[start_index, count]
|
24
32
|
data = mask(data.bytes.to_a, @masking_key).pack('C*') if @masking_key
|
25
33
|
data
|
26
34
|
end
|
27
35
|
|
28
|
-
#
|
29
|
-
unless new.respond_to?(:getbyte)
|
30
|
-
def getbyte(index)
|
31
|
-
self[index]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
36
|
+
# Mask whole payload using mask key
|
35
37
|
def mask(payload, mask)
|
36
38
|
return mask_native(payload, mask) if respond_to?(:mask_native)
|
37
39
|
result = []
|
@@ -2,7 +2,7 @@ module WebSocket
|
|
2
2
|
module Frame
|
3
3
|
module Handler
|
4
4
|
|
5
|
-
autoload :Base,
|
5
|
+
autoload :Base, "#{::WebSocket::ROOT}/websocket/frame/handler/base"
|
6
6
|
|
7
7
|
autoload :Handler03, "#{::WebSocket::ROOT}/websocket/frame/handler/handler03"
|
8
8
|
autoload :Handler04, "#{::WebSocket::ROOT}/websocket/frame/handler/handler04"
|
@@ -7,12 +7,12 @@ module WebSocket
|
|
7
7
|
|
8
8
|
# Hash of frame names and it's opcodes
|
9
9
|
FRAME_TYPES = {
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
10
|
+
continuation: 0,
|
11
|
+
close: 1,
|
12
|
+
ping: 2,
|
13
|
+
pong: 3,
|
14
|
+
text: 4,
|
15
|
+
binary: 5
|
16
16
|
}
|
17
17
|
|
18
18
|
# Hash of frame opcodes and it's names
|
@@ -37,12 +37,12 @@ module WebSocket
|
|
37
37
|
if length <= 125
|
38
38
|
byte2 = length # since rsv4 is 0
|
39
39
|
frame << (byte2 | mask)
|
40
|
-
elsif length <
|
40
|
+
elsif length < 65_536 # write 2 byte length
|
41
41
|
frame << (126 | mask)
|
42
42
|
frame << [length].pack('n')
|
43
43
|
else # write 8 byte length
|
44
44
|
frame << (127 | mask)
|
45
|
-
frame << [length >> 32, length & 0xFFFFFFFF].pack(
|
45
|
+
frame << [length >> 32, length & 0xFFFFFFFF].pack('NN')
|
46
46
|
end
|
47
47
|
|
48
48
|
if @frame.outgoing_masking?
|
@@ -83,16 +83,16 @@ module WebSocket
|
|
83
83
|
payload_length = case length
|
84
84
|
when 127 # Length defined by 8 bytes
|
85
85
|
# Check buffer size
|
86
|
-
return if @frame.data.getbyte(pointer+8-1) == nil # Buffer incomplete
|
86
|
+
return if @frame.data.getbyte(pointer + 8 - 1) == nil # Buffer incomplete
|
87
87
|
|
88
88
|
# Only using the last 4 bytes for now, till I work out how to
|
89
89
|
# unpack 8 bytes. I'm sure 4GB frames will do for now :)
|
90
|
-
l = @frame.data.getbytes(pointer+4, 4).unpack('N').first
|
90
|
+
l = @frame.data.getbytes(pointer + 4, 4).unpack('N').first
|
91
91
|
pointer += 8
|
92
92
|
l
|
93
93
|
when 126 # Length defined by 2 bytes
|
94
94
|
# Check buffer size
|
95
|
-
return if @frame.data.getbyte(pointer+2-1) == nil # Buffer incomplete
|
95
|
+
return if @frame.data.getbyte(pointer + 2 - 1) == nil # Buffer incomplete
|
96
96
|
|
97
97
|
l = @frame.data.getbytes(pointer, 2).unpack('n').first
|
98
98
|
pointer += 2
|
@@ -108,7 +108,7 @@ module WebSocket
|
|
108
108
|
raise(WebSocket::Error::Frame::TooLong) if frame_length > WebSocket.max_frame_size
|
109
109
|
|
110
110
|
# Check buffer size
|
111
|
-
return if @frame.data.getbyte(frame_length-1) == nil # Buffer incomplete
|
111
|
+
return if @frame.data.getbyte(frame_length - 1) == nil # Buffer incomplete
|
112
112
|
|
113
113
|
# Remove frame header
|
114
114
|
@frame.data.slice!(0...pointer)
|
@@ -118,7 +118,7 @@ module WebSocket
|
|
118
118
|
@frame.data.set_mask if mask
|
119
119
|
pointer += 4 if mask
|
120
120
|
application_data = @frame.data.getbytes(pointer, payload_length)
|
121
|
-
application_data.force_encoding('UTF-8')
|
121
|
+
application_data.force_encoding('UTF-8')
|
122
122
|
pointer += payload_length
|
123
123
|
@frame.data.unset_mask if mask
|
124
124
|
|
@@ -136,14 +136,14 @@ module WebSocket
|
|
136
136
|
if frame_type == :continuation
|
137
137
|
@application_data_buffer << application_data
|
138
138
|
# Test valid UTF-8 encoding
|
139
|
-
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if @frame_type == :text &&
|
140
|
-
message = @frame.class.new(:
|
139
|
+
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if @frame_type == :text && !@application_data_buffer.valid_encoding?
|
140
|
+
message = @frame.class.new(version: @frame.version, type: @frame_type, data: @application_data_buffer, decoded: true)
|
141
141
|
@application_data_buffer = nil
|
142
142
|
@frame_type = nil
|
143
143
|
return message
|
144
144
|
else
|
145
|
-
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if frame_type == :text &&
|
146
|
-
return @frame.class.new(:
|
145
|
+
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if frame_type == :text && !application_data.valid_encoding?
|
146
|
+
return @frame.class.new(version: @frame.version, type: frame_type, data: application_data, decoded: true)
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
@@ -7,12 +7,12 @@ module WebSocket
|
|
7
7
|
|
8
8
|
# Hash of frame names and it's opcodes
|
9
9
|
FRAME_TYPES = {
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
10
|
+
continuation: 0,
|
11
|
+
text: 1,
|
12
|
+
binary: 2,
|
13
|
+
close: 8,
|
14
|
+
ping: 9,
|
15
|
+
pong: 10,
|
16
16
|
}
|
17
17
|
|
18
18
|
# Hash of frame opcodes and it's names
|
@@ -42,11 +42,11 @@ module WebSocket
|
|
42
42
|
private
|
43
43
|
|
44
44
|
def valid_code?(code)
|
45
|
-
[1000,1001,1002,1003,1007,1008,1009,1010,1011].include?(code) || (3000..4999).include?(code)
|
45
|
+
[1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011].include?(code) || (3000..4999).include?(code)
|
46
46
|
end
|
47
47
|
|
48
48
|
def valid_encoding?(data)
|
49
|
-
return true if data.nil?
|
49
|
+
return true if data.nil?
|
50
50
|
data.encode('UTF-8')
|
51
51
|
true
|
52
52
|
rescue
|
@@ -16,8 +16,9 @@ module WebSocket
|
|
16
16
|
when :close then "\xff\x00"
|
17
17
|
when :text then
|
18
18
|
ary = ["\x00", @frame.data, "\xff"]
|
19
|
-
ary.
|
19
|
+
ary.map { |s| s.encode('UTF-8', 'UTF-8', invalid: :replace) }
|
20
20
|
ary.join
|
21
|
+
else raise WebSocket::Error::Frame::UnknownFrameType
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -34,7 +35,7 @@ module WebSocket
|
|
34
35
|
length = 0
|
35
36
|
|
36
37
|
loop do
|
37
|
-
return
|
38
|
+
return unless @frame.data.getbyte(pointer)
|
38
39
|
b = @frame.data.getbyte(pointer)
|
39
40
|
pointer += 1
|
40
41
|
b_v = b & 0x7F
|
@@ -44,15 +45,15 @@ module WebSocket
|
|
44
45
|
|
45
46
|
raise WebSocket::Error::Frame::TooLong if length > ::WebSocket.max_frame_size
|
46
47
|
|
47
|
-
unless @frame.data.getbyte(pointer+length-1) == nil
|
48
|
+
unless @frame.data.getbyte(pointer + length - 1) == nil
|
48
49
|
# Straight from spec - I'm sure this isn't crazy...
|
49
50
|
# 6. Read /length/ bytes.
|
50
51
|
# 7. Discard the read bytes.
|
51
|
-
@frame.instance_variable_set '@data', @frame.data[(pointer+length)..-1]
|
52
|
+
@frame.instance_variable_set '@data', @frame.data[(pointer + length)..-1]
|
52
53
|
|
53
54
|
# If the /frame type/ is 0xFF and the /length/ was 0, then close
|
54
55
|
if length == 0
|
55
|
-
@frame.class.new(:
|
56
|
+
@frame.class.new(version: @frame.version, type: :close, decoded: true)
|
56
57
|
end
|
57
58
|
end
|
58
59
|
else
|
@@ -66,8 +67,8 @@ module WebSocket
|
|
66
67
|
msg = @frame.data.slice!(/\A\x00[^\xff]*\xff/)
|
67
68
|
if msg
|
68
69
|
msg.gsub!(/\A\x00|\xff\z/, '')
|
69
|
-
msg.force_encoding('UTF-8')
|
70
|
-
@frame.class.new(:
|
70
|
+
msg.force_encoding('UTF-8')
|
71
|
+
@frame.class.new(version: @frame.version, type: :text, data: msg, decoded: true)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -4,7 +4,7 @@ module WebSocket
|
|
4
4
|
# @note You should NEVER use this class directly - use Client or Server subclasses instead, as they contain additional frame options(i.e. Client-side masking in draft 04)
|
5
5
|
#
|
6
6
|
# @example
|
7
|
-
# frame = WebSocket::Frame::Incoming::Server.new(:
|
7
|
+
# frame = WebSocket::Frame::Incoming::Server.new(version: @handshake.version)
|
8
8
|
# frame << "\x81\x05\x48\x65\x6c\x6c\x6f\x81\x06\x77\x6f\x72\x6c\x64\x21"
|
9
9
|
# frame.next # "Hello"
|
10
10
|
# frame.next # "world!""
|
@@ -4,7 +4,7 @@ module WebSocket
|
|
4
4
|
# @note You should NEVER use this class directly - use Client or Server subclasses instead, as they contain additional frame options(i.e. Client-side masking in draft 04)
|
5
5
|
#
|
6
6
|
# @example
|
7
|
-
# frame = WebSocket::Frame::Outgoing::Server.new(:
|
7
|
+
# frame = WebSocket::Frame::Outgoing::Server.new(version: @handshake.version, data: "Hello", type: :text)
|
8
8
|
# frame.to_s # "\x81\x05\x48\x65\x6c\x6c\x6f"
|
9
9
|
class Outgoing < Base
|
10
10
|
|
@@ -12,7 +12,7 @@ module WebSocket
|
|
12
12
|
@state = :new
|
13
13
|
@handler = nil
|
14
14
|
|
15
|
-
@data =
|
15
|
+
@data = ''
|
16
16
|
@headers = {}
|
17
17
|
end
|
18
18
|
|
@@ -24,13 +24,13 @@ module WebSocket
|
|
24
24
|
# Return textual representation of handshake request or response
|
25
25
|
# @return [String] text of response
|
26
26
|
def to_s
|
27
|
-
@handler ? @handler.to_s :
|
27
|
+
@handler ? @handler.to_s : ''
|
28
28
|
end
|
29
|
-
rescue_method :to_s, :
|
29
|
+
rescue_method :to_s, return: ''
|
30
30
|
|
31
31
|
# Recreate inspect as #to_s was overwritten
|
32
32
|
def inspect
|
33
|
-
vars = self.instance_variables.map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(
|
33
|
+
vars = self.instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
|
34
34
|
insp = "#{self.class}:0x%08x" % (self.__id__ * 2)
|
35
35
|
"<#{insp} #{vars}>"
|
36
36
|
end
|
@@ -46,7 +46,7 @@ module WebSocket
|
|
46
46
|
def valid?
|
47
47
|
finished? && @error == nil && @handler && @handler.valid?
|
48
48
|
end
|
49
|
-
rescue_method :valid?, :
|
49
|
+
rescue_method :valid?, return: false
|
50
50
|
|
51
51
|
# @abstract Should send data after parsing is finished?
|
52
52
|
def should_respond?
|
@@ -56,7 +56,7 @@ module WebSocket
|
|
56
56
|
# Data left from parsing. Sometimes data that doesn't belong to handshake are added - use this method to retrieve them.
|
57
57
|
# @return [String] String if some data are available. Nil otherwise
|
58
58
|
def leftovers
|
59
|
-
@leftovers.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines]
|
59
|
+
@leftovers.to_s.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines]
|
60
60
|
end
|
61
61
|
|
62
62
|
# URI of request.
|
@@ -64,7 +64,7 @@ module WebSocket
|
|
64
64
|
# @example
|
65
65
|
# @handshake.uri #=> "ws://example.com/path?query=true"
|
66
66
|
def uri
|
67
|
-
uri = secure ?
|
67
|
+
uri = secure ? 'wss://' : 'ws://'
|
68
68
|
uri << host
|
69
69
|
uri << ":#{port}" if port
|
70
70
|
uri << path
|
@@ -5,7 +5,7 @@ module WebSocket
|
|
5
5
|
# Construct or parse a client WebSocket handshake.
|
6
6
|
#
|
7
7
|
# @example
|
8
|
-
# @handshake = WebSocket::Handshake::Client.new(:
|
8
|
+
# @handshake = WebSocket::Handshake::Client.new(url: 'ws://example.com')
|
9
9
|
#
|
10
10
|
# # Create request
|
11
11
|
# @handshake.to_s # GET /demo HTTP/1.1
|
@@ -33,7 +33,7 @@ module WebSocket
|
|
33
33
|
#
|
34
34
|
class Client < Base
|
35
35
|
|
36
|
-
attr_reader :origin
|
36
|
+
attr_reader :origin, :headers
|
37
37
|
|
38
38
|
# Initialize new WebSocket Client
|
39
39
|
#
|
@@ -48,14 +48,16 @@ module WebSocket
|
|
48
48
|
# @option args [String] :url URL of request. Must by in format like ws://example.com/path?query=true. Every part of this url will be overriden by more specific arguments.
|
49
49
|
# @option args [String] :uri Alias to :url
|
50
50
|
# @option args [Integer] :version Version of WebSocket to use. Default: 13 (this is version from RFC)
|
51
|
+
# @option args [Hash] :headers HTTP headers to use in the handshake
|
51
52
|
#
|
52
53
|
# @example
|
53
|
-
# Websocket::Handshake::Client.new(:
|
54
|
+
# Websocket::Handshake::Client.new(url: "ws://example.com/path?query=true")
|
54
55
|
def initialize(args = {})
|
55
56
|
super
|
56
57
|
|
57
58
|
@version = args[:version] || DEFAULT_VERSION
|
58
59
|
@origin = args[:origin]
|
60
|
+
@headers = args[:headers] || {}
|
59
61
|
|
60
62
|
if args[:url] || args[:uri]
|
61
63
|
uri = URI.parse(args[:url] || args[:uri])
|