em-websocket 0.2.1 → 0.3.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/CHANGELOG.rdoc +10 -0
- data/README.md +16 -0
- data/examples/test.html +11 -8
- data/lib/em-websocket.rb +6 -3
- data/lib/em-websocket/close03.rb +11 -0
- data/lib/em-websocket/close05.rb +11 -0
- data/lib/em-websocket/close06.rb +16 -0
- data/lib/em-websocket/close75.rb +10 -0
- data/lib/em-websocket/connection.rb +58 -32
- data/lib/em-websocket/framing03.rb +9 -30
- data/lib/em-websocket/framing04.rb +15 -0
- data/lib/em-websocket/framing05.rb +157 -0
- data/lib/em-websocket/framing76.rb +5 -6
- data/lib/em-websocket/handler.rb +2 -4
- data/lib/em-websocket/handler03.rb +2 -6
- data/lib/em-websocket/handler05.rb +10 -0
- data/lib/em-websocket/handler06.rb +10 -0
- data/lib/em-websocket/handler75.rb +1 -0
- data/lib/em-websocket/handler76.rb +1 -0
- data/lib/em-websocket/handler_factory.rb +41 -22
- data/lib/em-websocket/handshake04.rb +35 -0
- data/lib/em-websocket/handshake75.rb +4 -4
- data/lib/em-websocket/handshake76.rb +8 -8
- data/lib/em-websocket/masking04.rb +27 -0
- data/lib/em-websocket/message_processor_03.rb +33 -0
- data/lib/em-websocket/message_processor_06.rb +46 -0
- data/lib/em-websocket/version.rb +1 -1
- data/spec/helper.rb +54 -2
- data/spec/integration/common_spec.rb +115 -0
- data/spec/integration/draft03_spec.rb +26 -11
- data/spec/integration/draft05_spec.rb +45 -0
- data/spec/integration/draft06_spec.rb +79 -0
- data/spec/integration/draft75_spec.rb +115 -0
- data/spec/integration/draft76_spec.rb +25 -10
- data/spec/integration/shared_examples.rb +62 -0
- data/spec/unit/framing_spec.rb +55 -0
- data/spec/unit/masking_spec.rb +18 -0
- metadata +29 -33
- data/spec/websocket_spec.rb +0 -210
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'integration/shared_examples'
|
2
3
|
|
3
4
|
describe "WebSocket server draft76" do
|
4
5
|
before :each do
|
@@ -30,6 +31,20 @@ describe "WebSocket server draft76" do
|
|
30
31
|
}
|
31
32
|
end
|
32
33
|
|
34
|
+
it_behaves_like "a websocket server" do
|
35
|
+
def start_server
|
36
|
+
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
37
|
+
yield ws
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_client
|
42
|
+
client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
|
43
|
+
client.send_data(format_request(@request))
|
44
|
+
yield client if block_given?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
33
48
|
it "should send back the correct handshake response" do
|
34
49
|
EM.run do
|
35
50
|
EM.add_timer(0.1) do
|
@@ -39,7 +54,7 @@ describe "WebSocket server draft76" do
|
|
39
54
|
connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
|
40
55
|
connection.send_data(format_request(@request))
|
41
56
|
|
42
|
-
connection.onopen
|
57
|
+
connection.onopen {
|
43
58
|
connection.handshake_response.lines.sort.
|
44
59
|
should == format_response(@response).lines.sort
|
45
60
|
EM.stop
|
@@ -58,13 +73,13 @@ describe "WebSocket server draft76" do
|
|
58
73
|
connection.send_data(format_request(@request))
|
59
74
|
|
60
75
|
# Send closing frame after handshake complete
|
61
|
-
connection.onopen
|
76
|
+
connection.onopen {
|
62
77
|
connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
|
63
78
|
}
|
64
79
|
|
65
80
|
# Check that this causes a termination string to be returned and the
|
66
81
|
# connection close
|
67
|
-
connection.onclose
|
82
|
+
connection.onclose {
|
68
83
|
connection.packets[0].should ==
|
69
84
|
EM::WebSocket::Handler76::TERMINATE_STRING
|
70
85
|
EM.stop
|
@@ -88,12 +103,12 @@ describe "WebSocket server draft76" do
|
|
88
103
|
connection.send_data(format_request(@request))
|
89
104
|
|
90
105
|
# Send closing frame after handshake complete, followed by another msg
|
91
|
-
connection.onopen
|
106
|
+
connection.onopen {
|
92
107
|
connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
|
93
108
|
connection.send('foobar')
|
94
109
|
}
|
95
110
|
|
96
|
-
connection.onclose
|
111
|
+
connection.onclose {
|
97
112
|
EM.stop
|
98
113
|
}
|
99
114
|
end
|
@@ -114,12 +129,12 @@ describe "WebSocket server draft76" do
|
|
114
129
|
connection.send_data(format_request(@request))
|
115
130
|
|
116
131
|
# Send closing frame after handshake complete
|
117
|
-
connection.onopen
|
132
|
+
connection.onopen {
|
118
133
|
connection.send_data("\000\n\000\377")
|
119
134
|
connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
|
120
135
|
}
|
121
136
|
|
122
|
-
connection.onclose
|
137
|
+
connection.onclose {
|
123
138
|
EM.stop
|
124
139
|
}
|
125
140
|
end
|
@@ -144,7 +159,7 @@ describe "WebSocket server draft76" do
|
|
144
159
|
# 1180591620717411303296 bytes. Such a message would previously cause
|
145
160
|
# a "bignum too big to convert into `long'" error.
|
146
161
|
# However it is clearly unreasonable and should be rejected.
|
147
|
-
client.onopen
|
162
|
+
client.onopen {
|
148
163
|
client.send_data("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00")
|
149
164
|
}
|
150
165
|
end
|
@@ -164,7 +179,7 @@ describe "WebSocket server draft76" do
|
|
164
179
|
client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
|
165
180
|
client.send_data(format_request(@request))
|
166
181
|
|
167
|
-
client.onopen
|
182
|
+
client.onopen {
|
168
183
|
client.send_data("foobar") # Does not start with \x00 or \xff
|
169
184
|
}
|
170
185
|
end
|
@@ -196,7 +211,7 @@ describe "WebSocket server draft76" do
|
|
196
211
|
# Sends first half of the request
|
197
212
|
connection.send_data(data[0...(data.length / 2)])
|
198
213
|
|
199
|
-
connection.onopen
|
214
|
+
connection.onopen {
|
200
215
|
connection.handshake_response.lines.sort.
|
201
216
|
should == format_response(@response).lines.sort
|
202
217
|
EM.stop
|
@@ -0,0 +1,62 @@
|
|
1
|
+
shared_examples_for "a websocket server" do
|
2
|
+
it "should call onerror if an application error raised in onopen" do
|
3
|
+
EM.run {
|
4
|
+
start_server { |ws|
|
5
|
+
ws.onopen {
|
6
|
+
raise "application error"
|
7
|
+
}
|
8
|
+
|
9
|
+
ws.onerror { |e|
|
10
|
+
e.message.should == "application error"
|
11
|
+
EM.stop
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
start_client
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should call onerror if an application error raised in onmessage" do
|
20
|
+
EM.run {
|
21
|
+
start_server { |server|
|
22
|
+
server.onmessage {
|
23
|
+
raise "application error"
|
24
|
+
}
|
25
|
+
|
26
|
+
server.onerror { |e|
|
27
|
+
e.message.should == "application error"
|
28
|
+
EM.stop
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
start_client { |client|
|
33
|
+
client.onopen {
|
34
|
+
client.send('a message')
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should call onerror in an application error raised in onclose" do
|
41
|
+
EM.run {
|
42
|
+
start_server { |server|
|
43
|
+
server.onclose {
|
44
|
+
raise "application error"
|
45
|
+
}
|
46
|
+
|
47
|
+
server.onerror { |e|
|
48
|
+
e.message.should == "application error"
|
49
|
+
EM.stop
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
start_client { |client|
|
54
|
+
client.onopen {
|
55
|
+
EM.add_timer(0.1) {
|
56
|
+
client.close_connection
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
data/spec/unit/framing_spec.rb
CHANGED
@@ -106,3 +106,58 @@ describe EM::WebSocket::Framing03 do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
109
|
+
|
110
|
+
# These examples are straight from the spec
|
111
|
+
# http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6
|
112
|
+
describe EM::WebSocket::Framing04 do
|
113
|
+
class FramingContainer04
|
114
|
+
include EM::WebSocket::Framing04
|
115
|
+
|
116
|
+
def <<(data)
|
117
|
+
@data << data
|
118
|
+
process_data(data)
|
119
|
+
end
|
120
|
+
|
121
|
+
def debug(*args); end
|
122
|
+
end
|
123
|
+
|
124
|
+
before :each do
|
125
|
+
@f = FramingContainer04.new
|
126
|
+
@f.initialize_framing
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "examples from the spec" do
|
130
|
+
it "a single-frame text message" do
|
131
|
+
@f.should_receive(:message).with(:text, '', 'Hello')
|
132
|
+
@f << "\x84\x05\x48\x65\x6c\x6c\x6f" # "\x84\x05Hello"
|
133
|
+
end
|
134
|
+
|
135
|
+
it "a fragmented text message" do
|
136
|
+
@f.should_receive(:message).with(:text, '', 'Hello')
|
137
|
+
@f << "\x04\x03Hel"
|
138
|
+
@f << "\x80\x02lo"
|
139
|
+
end
|
140
|
+
|
141
|
+
it "Ping request" do
|
142
|
+
@f.should_receive(:message).with(:ping, '', 'Hello')
|
143
|
+
@f << "\x82\x05Hello"
|
144
|
+
end
|
145
|
+
|
146
|
+
it "a pong response" do
|
147
|
+
@f.should_receive(:message).with(:pong, '', 'Hello')
|
148
|
+
@f << "\x83\x05Hello"
|
149
|
+
end
|
150
|
+
|
151
|
+
it "256 bytes binary message in a single frame" do
|
152
|
+
data = "a"*256
|
153
|
+
@f.should_receive(:message).with(:binary, '', data)
|
154
|
+
@f << "\x85\x7E\x01\x00" + data
|
155
|
+
end
|
156
|
+
|
157
|
+
it "64KiB binary message in a single frame" do
|
158
|
+
data = "a"*65536
|
159
|
+
@f.should_receive(:message).with(:binary, '', data)
|
160
|
+
@f << "\x85\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe EM::WebSocket::MaskedString do
|
4
|
+
it "should allow reading 4 byte mask and unmasking byte / bytes" do
|
5
|
+
t = EM::WebSocket::MaskedString.new("\x00\x00\x00\x01\x00\x01\x00\x01")
|
6
|
+
t.read_mask
|
7
|
+
t.getbyte(3).should == 0x00
|
8
|
+
t.getbytes(0, 4).should == "\x00\x01\x00\x00"
|
9
|
+
t.getbytes(1, 3).should == "\x01\x00\x00"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return nil from getbyte if index requested is out of range" do
|
13
|
+
t = EM::WebSocket::MaskedString.new("\x00\x00\x00\x00\x53")
|
14
|
+
t.read_mask
|
15
|
+
t.getbyte(0).should == 0x53
|
16
|
+
t.getbyte(1).should == nil
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-websocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 2
|
8
|
-
- 1
|
9
|
-
version: 0.2.1
|
4
|
+
prerelease:
|
5
|
+
version: 0.3.0
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Ilya Grigorik
|
@@ -14,7 +10,7 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date: 2011-
|
13
|
+
date: 2011-05-06 00:00:00 +01:00
|
18
14
|
default_executable:
|
19
15
|
dependencies:
|
20
16
|
- !ruby/object:Gem::Dependency
|
@@ -25,10 +21,6 @@ dependencies:
|
|
25
21
|
requirements:
|
26
22
|
- - ">="
|
27
23
|
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 0
|
30
|
-
- 12
|
31
|
-
- 9
|
32
24
|
version: 0.12.9
|
33
25
|
type: :runtime
|
34
26
|
version_requirements: *id001
|
@@ -40,10 +32,6 @@ dependencies:
|
|
40
32
|
requirements:
|
41
33
|
- - ">="
|
42
34
|
- !ruby/object:Gem::Version
|
43
|
-
segments:
|
44
|
-
- 2
|
45
|
-
- 1
|
46
|
-
- 1
|
47
35
|
version: 2.1.1
|
48
36
|
type: :runtime
|
49
37
|
version_requirements: *id002
|
@@ -55,10 +43,6 @@ dependencies:
|
|
55
43
|
requirements:
|
56
44
|
- - ~>
|
57
45
|
- !ruby/object:Gem::Version
|
58
|
-
segments:
|
59
|
-
- 0
|
60
|
-
- 2
|
61
|
-
- 6
|
62
46
|
version: 0.2.6
|
63
47
|
type: :development
|
64
48
|
version_requirements: *id003
|
@@ -70,11 +54,7 @@ dependencies:
|
|
70
54
|
requirements:
|
71
55
|
- - ~>
|
72
56
|
- !ruby/object:Gem::Version
|
73
|
-
|
74
|
-
- 2
|
75
|
-
- 0
|
76
|
-
- 0
|
77
|
-
version: 2.0.0
|
57
|
+
version: 2.5.0
|
78
58
|
type: :development
|
79
59
|
version_requirements: *id004
|
80
60
|
- !ruby/object:Gem::Dependency
|
@@ -85,8 +65,6 @@ dependencies:
|
|
85
65
|
requirements:
|
86
66
|
- - ">="
|
87
67
|
- !ruby/object:Gem::Version
|
88
|
-
segments:
|
89
|
-
- 0
|
90
68
|
version: "0"
|
91
69
|
type: :development
|
92
70
|
version_requirements: *id005
|
@@ -114,25 +92,42 @@ files:
|
|
114
92
|
- examples/multicast.rb
|
115
93
|
- examples/test.html
|
116
94
|
- lib/em-websocket.rb
|
95
|
+
- lib/em-websocket/close03.rb
|
96
|
+
- lib/em-websocket/close05.rb
|
97
|
+
- lib/em-websocket/close06.rb
|
98
|
+
- lib/em-websocket/close75.rb
|
117
99
|
- lib/em-websocket/connection.rb
|
118
100
|
- lib/em-websocket/debugger.rb
|
119
101
|
- lib/em-websocket/framing03.rb
|
102
|
+
- lib/em-websocket/framing04.rb
|
103
|
+
- lib/em-websocket/framing05.rb
|
120
104
|
- lib/em-websocket/framing76.rb
|
121
105
|
- lib/em-websocket/handler.rb
|
122
106
|
- lib/em-websocket/handler03.rb
|
107
|
+
- lib/em-websocket/handler05.rb
|
108
|
+
- lib/em-websocket/handler06.rb
|
123
109
|
- lib/em-websocket/handler75.rb
|
124
110
|
- lib/em-websocket/handler76.rb
|
125
111
|
- lib/em-websocket/handler_factory.rb
|
112
|
+
- lib/em-websocket/handshake04.rb
|
126
113
|
- lib/em-websocket/handshake75.rb
|
127
114
|
- lib/em-websocket/handshake76.rb
|
115
|
+
- lib/em-websocket/masking04.rb
|
116
|
+
- lib/em-websocket/message_processor_03.rb
|
117
|
+
- lib/em-websocket/message_processor_06.rb
|
128
118
|
- lib/em-websocket/version.rb
|
129
119
|
- lib/em-websocket/websocket.rb
|
130
120
|
- spec/helper.rb
|
121
|
+
- spec/integration/common_spec.rb
|
131
122
|
- spec/integration/draft03_spec.rb
|
123
|
+
- spec/integration/draft05_spec.rb
|
124
|
+
- spec/integration/draft06_spec.rb
|
125
|
+
- spec/integration/draft75_spec.rb
|
132
126
|
- spec/integration/draft76_spec.rb
|
127
|
+
- spec/integration/shared_examples.rb
|
133
128
|
- spec/unit/framing_spec.rb
|
134
129
|
- spec/unit/handler_spec.rb
|
135
|
-
- spec/
|
130
|
+
- spec/unit/masking_spec.rb
|
136
131
|
has_rdoc: true
|
137
132
|
homepage: http://github.com/igrigorik/em-websocket
|
138
133
|
licenses: []
|
@@ -147,28 +142,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
142
|
requirements:
|
148
143
|
- - ">="
|
149
144
|
- !ruby/object:Gem::Version
|
150
|
-
segments:
|
151
|
-
- 0
|
152
145
|
version: "0"
|
153
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
147
|
none: false
|
155
148
|
requirements:
|
156
149
|
- - ">="
|
157
150
|
- !ruby/object:Gem::Version
|
158
|
-
segments:
|
159
|
-
- 0
|
160
151
|
version: "0"
|
161
152
|
requirements: []
|
162
153
|
|
163
154
|
rubyforge_project: em-websocket
|
164
|
-
rubygems_version: 1.
|
155
|
+
rubygems_version: 1.6.2
|
165
156
|
signing_key:
|
166
157
|
specification_version: 3
|
167
158
|
summary: EventMachine based WebSocket server
|
168
159
|
test_files:
|
169
160
|
- spec/helper.rb
|
161
|
+
- spec/integration/common_spec.rb
|
170
162
|
- spec/integration/draft03_spec.rb
|
163
|
+
- spec/integration/draft05_spec.rb
|
164
|
+
- spec/integration/draft06_spec.rb
|
165
|
+
- spec/integration/draft75_spec.rb
|
171
166
|
- spec/integration/draft76_spec.rb
|
167
|
+
- spec/integration/shared_examples.rb
|
172
168
|
- spec/unit/framing_spec.rb
|
173
169
|
- spec/unit/handler_spec.rb
|
174
|
-
- spec/
|
170
|
+
- spec/unit/masking_spec.rb
|
data/spec/websocket_spec.rb
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe EventMachine::WebSocket do
|
4
|
-
|
5
|
-
it "should automatically complete WebSocket handshake" do
|
6
|
-
EM.run do
|
7
|
-
MSG = "Hello World!"
|
8
|
-
EventMachine.add_timer(0.1) do
|
9
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
10
|
-
http.errback { failed }
|
11
|
-
http.callback { http.response_header.status.should == 101 }
|
12
|
-
|
13
|
-
http.stream { |msg|
|
14
|
-
msg.should == MSG
|
15
|
-
EventMachine.stop
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
20
|
-
ws.onopen {
|
21
|
-
ws.send MSG
|
22
|
-
}
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should fail on non WebSocket requests" do
|
28
|
-
EM.run do
|
29
|
-
EventMachine.add_timer(0.1) do
|
30
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:12345/').get :timeout => 0
|
31
|
-
http.errback { failed }
|
32
|
-
http.callback {
|
33
|
-
http.response_header.status.should == 400
|
34
|
-
EventMachine.stop
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) {}
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should split multiple messages into separate callbacks" do
|
43
|
-
EM.run do
|
44
|
-
messages = %w[1 2]
|
45
|
-
received = []
|
46
|
-
|
47
|
-
EventMachine.add_timer(0.1) do
|
48
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
49
|
-
http.errback { failed }
|
50
|
-
http.stream {|msg|}
|
51
|
-
http.callback {
|
52
|
-
http.response_header.status.should == 101
|
53
|
-
http.send messages[0]
|
54
|
-
http.send messages[1]
|
55
|
-
}
|
56
|
-
end
|
57
|
-
|
58
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
59
|
-
ws.onopen {}
|
60
|
-
ws.onclose {}
|
61
|
-
ws.onmessage {|msg|
|
62
|
-
msg.should == messages[received.size]
|
63
|
-
received.push msg
|
64
|
-
|
65
|
-
EventMachine.stop if received.size == messages.size
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should call onclose callback when client closes connection" do
|
72
|
-
EM.run do
|
73
|
-
EventMachine.add_timer(0.1) do
|
74
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
75
|
-
http.errback { failed }
|
76
|
-
http.callback {
|
77
|
-
http.response_header.status.should == 101
|
78
|
-
http.close_connection
|
79
|
-
}
|
80
|
-
http.stream{|msg|}
|
81
|
-
end
|
82
|
-
|
83
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
84
|
-
ws.onopen {}
|
85
|
-
ws.onclose {
|
86
|
-
ws.state.should == :closed
|
87
|
-
EventMachine.stop
|
88
|
-
}
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should call onerror callback with raised exception and close connection on bad handshake" do
|
94
|
-
EM.run do
|
95
|
-
EventMachine.add_timer(0.1) do
|
96
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:12345/').get :timeout => 0
|
97
|
-
http.errback { http.response_header.status.should == 0 }
|
98
|
-
http.callback { failed }
|
99
|
-
end
|
100
|
-
|
101
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
102
|
-
ws.onopen { failed }
|
103
|
-
ws.onclose { EventMachine.stop }
|
104
|
-
ws.onerror {|e|
|
105
|
-
e.should be_an_instance_of EventMachine::WebSocket::HandshakeError
|
106
|
-
e.message.should match('Connection and Upgrade headers required')
|
107
|
-
EventMachine.stop
|
108
|
-
}
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
it "should populate ws.request with appropriate headers" do
|
114
|
-
EM.run do
|
115
|
-
EventMachine.add_timer(0.1) do
|
116
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
117
|
-
http.errback { failed }
|
118
|
-
http.callback {
|
119
|
-
http.response_header.status.should == 101
|
120
|
-
http.close_connection
|
121
|
-
}
|
122
|
-
http.stream { |msg| }
|
123
|
-
end
|
124
|
-
|
125
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
126
|
-
ws.onopen {
|
127
|
-
ws.request["User-Agent"].should == "EventMachine HttpClient"
|
128
|
-
ws.request["Connection"].should == "Upgrade"
|
129
|
-
ws.request["Upgrade"].should == "WebSocket"
|
130
|
-
ws.request["Path"].should == "/"
|
131
|
-
ws.request["Origin"].should == "127.0.0.1"
|
132
|
-
ws.request["Host"].to_s.should == "ws://127.0.0.1:12345"
|
133
|
-
}
|
134
|
-
ws.onclose {
|
135
|
-
ws.state.should == :closed
|
136
|
-
EventMachine.stop
|
137
|
-
}
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should allow sending and retrieving query string args passed in on the connection request." do
|
143
|
-
EM.run do
|
144
|
-
EventMachine.add_timer(0.1) do
|
145
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get(:query => {'foo' => 'bar', 'baz' => 'qux'}, :timeout => 0)
|
146
|
-
http.errback { failed }
|
147
|
-
http.callback {
|
148
|
-
http.response_header.status.should == 101
|
149
|
-
http.close_connection
|
150
|
-
}
|
151
|
-
http.stream { |msg| }
|
152
|
-
end
|
153
|
-
|
154
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
155
|
-
ws.onopen {
|
156
|
-
path, query = ws.request["Path"].split('?')
|
157
|
-
path.should == '/'
|
158
|
-
Hash[*query.split(/&|=/)].should == {"foo"=>"bar", "baz"=>"qux"}
|
159
|
-
ws.request["Query"]["foo"].should == "bar"
|
160
|
-
ws.request["Query"]["baz"].should == "qux"
|
161
|
-
}
|
162
|
-
ws.onclose {
|
163
|
-
ws.state.should == :closed
|
164
|
-
EventMachine.stop
|
165
|
-
}
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should ws.response['Query'] to empty hash when no query string params passed in connection URI" do
|
171
|
-
EM.run do
|
172
|
-
EventMachine.add_timer(0.1) do
|
173
|
-
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get(:timeout => 0)
|
174
|
-
http.errback { failed }
|
175
|
-
http.callback {
|
176
|
-
http.response_header.status.should == 101
|
177
|
-
http.close_connection
|
178
|
-
}
|
179
|
-
http.stream { |msg| }
|
180
|
-
end
|
181
|
-
|
182
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
183
|
-
ws.onopen {
|
184
|
-
ws.request["Path"].should == "/"
|
185
|
-
ws.request["Query"].should == {}
|
186
|
-
}
|
187
|
-
ws.onclose {
|
188
|
-
ws.state.should == :closed
|
189
|
-
EventMachine.stop
|
190
|
-
}
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should raise an exception if frame sent before handshake complete" do
|
196
|
-
EM.run {
|
197
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |c|
|
198
|
-
# We're not using a real client so the handshake will not be sent
|
199
|
-
EM.add_timer(0.1) {
|
200
|
-
lambda {
|
201
|
-
c.send('early message')
|
202
|
-
}.should raise_error('Cannot send data before onopen callback')
|
203
|
-
EM.stop
|
204
|
-
}
|
205
|
-
}
|
206
|
-
|
207
|
-
client = EM.connect('0.0.0.0', 12345, EM::Connection)
|
208
|
-
}
|
209
|
-
end
|
210
|
-
end
|