websocket 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: [![](https://travis-ci.org/imanel/websocket-ruby.png)](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
|
+
[![Gem Version](https://badge.fury.io/rb/websocket.svg)](http://badge.fury.io/rb/websocket)
|
6
|
+
[![Travis CI](https://travis-ci.org/imanel/websocket-ruby.png)](http://travis-ci.org/imanel/websocket-ruby)
|
7
|
+
[![Code Climate](https://codeclimate.com/github/imanel/websocket-ruby.png)](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])
|