websocket-rack 0.1.4 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/README.md +42 -24
  3. data/Rakefile +1 -1
  4. data/example/example.ru +5 -5
  5. data/lib/rack/websocket/application.rb +31 -60
  6. data/lib/rack/websocket/extensions/common.rb +61 -0
  7. data/lib/rack/websocket/extensions/thin/connection.rb +2 -50
  8. data/lib/rack/websocket/extensions/thin.rb +3 -3
  9. data/lib/rack/websocket/extensions.rb +14 -0
  10. data/lib/rack/websocket/handler/base.rb +41 -0
  11. data/lib/rack/websocket/handler/stub.rb +14 -0
  12. data/lib/rack/websocket/handler/thin/connection.rb +89 -0
  13. data/lib/rack/websocket/handler/thin/handler_factory.rb +56 -0
  14. data/lib/rack/websocket/handler/thin.rb +61 -0
  15. data/lib/rack/websocket/handler.rb +15 -38
  16. data/lib/rack/websocket/version.rb +5 -0
  17. data/lib/rack/websocket.rb +5 -31
  18. data/spec/spec_helper.rb +18 -0
  19. data/spec/support/all_drafts.rb +43 -0
  20. data/spec/support/all_handlers.rb +31 -0
  21. data/spec/support/requests.rb +100 -0
  22. data/spec/thin_spec.rb +46 -0
  23. data/websocket-rack.gemspec +4 -4
  24. metadata +41 -47
  25. data/lib/rack/websocket/connection.rb +0 -112
  26. data/lib/rack/websocket/debugger.rb +0 -17
  27. data/lib/rack/websocket/framing03.rb +0 -178
  28. data/lib/rack/websocket/framing76.rb +0 -115
  29. data/lib/rack/websocket/handler03.rb +0 -14
  30. data/lib/rack/websocket/handler75.rb +0 -8
  31. data/lib/rack/websocket/handler76.rb +0 -11
  32. data/lib/rack/websocket/handler_factory.rb +0 -61
  33. data/lib/rack/websocket/handshake75.rb +0 -21
  34. data/lib/rack/websocket/handshake76.rb +0 -71
  35. data/spec/helper.rb +0 -44
  36. data/spec/integration/draft03_spec.rb +0 -252
  37. data/spec/integration/draft76_spec.rb +0 -212
  38. data/spec/unit/framing_spec.rb +0 -108
  39. data/spec/unit/handler_spec.rb +0 -136
  40. data/spec/websocket_spec.rb +0 -210
@@ -1,252 +0,0 @@
1
- # require 'helper'
2
- #
3
- # describe "draft03" do
4
- # before :each do
5
- # @request = {
6
- # :port => 80,
7
- # :method => "GET",
8
- # :path => "/demo",
9
- # :headers => {
10
- # 'Host' => 'example.com',
11
- # 'Connection' => 'Upgrade',
12
- # 'Sec-WebSocket-Key2' => '12998 5 Y3 1 .P00',
13
- # 'Sec-WebSocket-Protocol' => 'sample',
14
- # 'Upgrade' => 'WebSocket',
15
- # 'Sec-WebSocket-Key1' => '4 @1 46546xW%0l 1 5',
16
- # 'Origin' => 'http://example.com',
17
- # 'Sec-WebSocket-Draft' => '3'
18
- # },
19
- # :body => '^n:ds[4U'
20
- # }
21
- #
22
- # @response = {
23
- # :headers => {
24
- # "Upgrade" => "WebSocket",
25
- # "Connection" => "Upgrade",
26
- # "Sec-WebSocket-Location" => "ws://example.com/demo",
27
- # "Sec-WebSocket-Origin" => "http://example.com",
28
- # "Sec-WebSocket-Protocol" => "sample"
29
- # },
30
- # :body => "8jKS\'y:G*Co,Wxa-"
31
- # }
32
- # end
33
- #
34
- # # These examples are straight from the spec
35
- # # http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6
36
- # describe "examples from the spec" do
37
- # it "should accept a single-frame text message" do
38
- # EM.run do
39
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
40
- # ws.onmessage { |msg|
41
- # msg.should == 'Hello'
42
- # EM.stop
43
- # }
44
- # }
45
- #
46
- # # Create a fake client which sends draft 76 handshake
47
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
48
- # connection.send_data(format_request(@request))
49
- #
50
- # # Send frame
51
- # connection.onopen = lambda {
52
- # connection.send_data("\x04\x05Hello")
53
- # }
54
- # end
55
- # end
56
- #
57
- # it "should accept a fragmented text message" do
58
- # EM.run do
59
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
60
- # ws.onmessage { |msg|
61
- # msg.should == 'Hello'
62
- # EM.stop
63
- # }
64
- # }
65
- #
66
- # # Create a fake client which sends draft 76 handshake
67
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
68
- # connection.send_data(format_request(@request))
69
- #
70
- # # Send frame
71
- # connection.onopen = lambda {
72
- # connection.send_data("\x84\x03Hel")
73
- # connection.send_data("\x00\x02lo")
74
- # }
75
- # end
76
- # end
77
- #
78
- # it "should accept a ping request and respond with the same body" do
79
- # EM.run do
80
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws| }
81
- #
82
- # # Create a fake client which sends draft 76 handshake
83
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
84
- # connection.send_data(format_request(@request))
85
- #
86
- # # Send frame
87
- # connection.onopen = lambda {
88
- # connection.send_data("\x02\x05Hello")
89
- # }
90
- #
91
- # connection.onmessage = lambda { |frame|
92
- # next if frame.nil?
93
- # frame.should == "\x03\x05Hello"
94
- # EM.stop
95
- # }
96
- # end
97
- # end
98
- #
99
- # it "should accept a 256 bytes binary message in a single frame" do
100
- # EM.run do
101
- # data = "a" * 256
102
- #
103
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
104
- # ws.onmessage { |msg|
105
- # msg.should == data
106
- # EM.stop
107
- # }
108
- # }
109
- #
110
- # # Create a fake client which sends draft 76 handshake
111
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
112
- # connection.send_data(format_request(@request))
113
- #
114
- # # Send frame
115
- # connection.onopen = lambda {
116
- # connection.send_data("\x05\x7E\x01\x00" + data)
117
- # }
118
- # end
119
- # end
120
- #
121
- # it "should accept a 64KiB binary message in a single frame" do
122
- # EM.run do
123
- # data = "a" * 65536
124
- #
125
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
126
- # ws.onmessage { |msg|
127
- # msg.should == data
128
- # EM.stop
129
- # }
130
- # }
131
- #
132
- # # Create a fake client which sends draft 76 handshake
133
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
134
- # connection.send_data(format_request(@request))
135
- #
136
- # # Send frame
137
- # connection.onopen = lambda {
138
- # connection.send_data("\x05\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data)
139
- # }
140
- # end
141
- # end
142
- # end
143
- #
144
- # describe "close handling" do
145
- # it "should respond to a new close frame with a close frame" do
146
- # EM.run do
147
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws| }
148
- #
149
- # # Create a fake client which sends draft 76 handshake
150
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
151
- # connection.send_data(format_request(@request))
152
- #
153
- # # Send close frame
154
- # connection.onopen = lambda {
155
- # connection.send_data("\x01\x00")
156
- # }
157
- #
158
- # # Check that close ack received
159
- # connection.onmessage = lambda { |frame|
160
- # frame.should == "\x01\x00"
161
- # EM.stop
162
- # }
163
- # end
164
- # end
165
- #
166
- # it "should close the connection on receiving a close acknowlegement" do
167
- # EM.run do
168
- # ack_received = false
169
- #
170
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
171
- # ws.onopen {
172
- # # 2. Send a close frame
173
- # EM.next_tick {
174
- # ws.close_websocket
175
- # }
176
- # }
177
- # }
178
- #
179
- # # 1. Create a fake client which sends draft 76 handshake
180
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
181
- # connection.send_data(format_request(@request))
182
- #
183
- # # 3. Check that close frame recieved and acknowlege it
184
- # connection.onmessage = lambda { |frame|
185
- # frame.should == "\x01\x00"
186
- # ack_received = true
187
- # connection.send_data("\x01\x00")
188
- # }
189
- #
190
- # # 4. Check that connection is closed _after_ the ack
191
- # connection.onclose = lambda {
192
- # ack_received.should == true
193
- # EM.stop
194
- # }
195
- # end
196
- # end
197
- #
198
- # it "should not allow data frame to be sent after close frame sent" do
199
- # EM.run {
200
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
201
- # ws.onopen {
202
- # # 2. Send a close frame
203
- # EM.next_tick {
204
- # ws.close_websocket
205
- # }
206
- #
207
- # # 3. Check that exception raised if I attempt to send more data
208
- # EM.add_timer(0.1) {
209
- # lambda {
210
- # ws.send('hello world')
211
- # }.should raise_error(EM::WebSocket::WebSocketError, 'Cannot send data frame since connection is closing')
212
- # EM.stop
213
- # }
214
- # }
215
- # }
216
- #
217
- # # 1. Create a fake client which sends draft 76 handshake
218
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
219
- # connection.send_data(format_request(@request))
220
- # }
221
- # end
222
- #
223
- # it "should still respond to control frames after close frame sent" do
224
- # EM.run {
225
- # EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
226
- # ws.onopen {
227
- # # 2. Send a close frame
228
- # EM.next_tick {
229
- # ws.close_websocket
230
- # }
231
- # }
232
- # }
233
- #
234
- # # 1. Create a fake client which sends draft 76 handshake
235
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
236
- # connection.send_data(format_request(@request))
237
- #
238
- # connection.onmessage = lambda { |frame|
239
- # if frame == "\x01\x00"
240
- # # 3. After the close frame is received send a ping frame, but
241
- # # don't respond with a close ack
242
- # connection.send_data("\x02\x05Hello")
243
- # else
244
- # # 4. Check that the pong is received
245
- # frame.should == "\x03\x05Hello"
246
- # EM.stop
247
- # end
248
- # }
249
- # }
250
- # end
251
- # end
252
- # end
@@ -1,212 +0,0 @@
1
- # require 'helper'
2
- #
3
- # describe "WebSocket server draft76" do
4
- # before :each do
5
- # @request = {
6
- # :port => 80,
7
- # :method => "GET",
8
- # :path => "/demo",
9
- # :headers => {
10
- # 'Host' => 'example.com',
11
- # 'Connection' => 'Upgrade',
12
- # 'Sec-WebSocket-Key2' => '12998 5 Y3 1 .P00',
13
- # 'Sec-WebSocket-Protocol' => 'sample',
14
- # 'Upgrade' => 'WebSocket',
15
- # 'Sec-WebSocket-Key1' => '4 @1 46546xW%0l 1 5',
16
- # 'Origin' => 'http://example.com'
17
- # },
18
- # :body => '^n:ds[4U'
19
- # }
20
- #
21
- # @response = {
22
- # :headers => {
23
- # "Upgrade" => "WebSocket",
24
- # "Connection" => "Upgrade",
25
- # "Sec-WebSocket-Location" => "ws://example.com/demo",
26
- # "Sec-WebSocket-Origin" => "http://example.com",
27
- # "Sec-WebSocket-Protocol" => "sample"
28
- # },
29
- # :body => "8jKS\'y:G*Co,Wxa-"
30
- # }
31
- # end
32
- #
33
- # it "should send back the correct handshake response" do
34
- # EM.run do
35
- # EM.add_timer(0.1) do
36
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
37
- #
38
- # # Create a fake client which sends draft 76 handshake
39
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
40
- # connection.send_data(format_request(@request))
41
- #
42
- # connection.onopen = lambda {
43
- # connection.handshake_response.lines.sort.
44
- # should == format_response(@response).lines.sort
45
- # EM.stop
46
- # }
47
- # end
48
- # end
49
- # end
50
- #
51
- # it "should send closing frame back and close the connection after recieving closing frame" do
52
- # EM.run do
53
- # EM.add_timer(0.1) do
54
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
55
- #
56
- # # Create a fake client which sends draft 76 handshake
57
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
58
- # connection.send_data(format_request(@request))
59
- #
60
- # # Send closing frame after handshake complete
61
- # connection.onopen = lambda {
62
- # connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
63
- # }
64
- #
65
- # # Check that this causes a termination string to be returned and the
66
- # # connection close
67
- # connection.onclose = lambda {
68
- # connection.packets[0].should ==
69
- # EM::WebSocket::Handler76::TERMINATE_STRING
70
- # EM.stop
71
- # }
72
- # end
73
- # end
74
- # end
75
- #
76
- # it "should ignore any data received after the closing frame" do
77
- # EM.run do
78
- # EM.add_timer(0.1) do
79
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
80
- # # Fail if foobar message is received
81
- # ws.onmessage { |msg|
82
- # failed
83
- # }
84
- # }
85
- #
86
- # # Create a fake client which sends draft 76 handshake
87
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
88
- # connection.send_data(format_request(@request))
89
- #
90
- # # Send closing frame after handshake complete, followed by another msg
91
- # connection.onopen = lambda {
92
- # connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
93
- # connection.send('foobar')
94
- # }
95
- #
96
- # connection.onclose = lambda {
97
- # EM.stop
98
- # }
99
- # end
100
- # end
101
- # end
102
- #
103
- # it "should accept null bytes within the frame after a line return" do
104
- # EM.run do
105
- # EM.add_timer(0.1) do
106
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
107
- # ws.onmessage { |msg|
108
- # msg.should == "\n\000"
109
- # }
110
- # }
111
- #
112
- # # Create a fake client which sends draft 76 handshake
113
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
114
- # connection.send_data(format_request(@request))
115
- #
116
- # # Send closing frame after handshake complete
117
- # connection.onopen = lambda {
118
- # connection.send_data("\000\n\000\377")
119
- # connection.send_data(EM::WebSocket::Handler76::TERMINATE_STRING)
120
- # }
121
- #
122
- # connection.onclose = lambda {
123
- # EM.stop
124
- # }
125
- # end
126
- # end
127
- # end
128
- #
129
- # it "should handle unreasonable frame lengths by calling onerror callback" do
130
- # EM.run do
131
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
132
- # server.onerror { |error|
133
- # error.should be_an_instance_of EM::WebSocket::DataError
134
- # error.message.should == "Frame length too long (1180591620717411303296 bytes)"
135
- # EM.stop
136
- # }
137
- # }
138
- #
139
- # # Create a fake client which sends draft 76 handshake
140
- # client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
141
- # client.send_data(format_request(@request))
142
- #
143
- # # This particular frame indicates a message length of
144
- # # 1180591620717411303296 bytes. Such a message would previously cause
145
- # # a "bignum too big to convert into `long'" error.
146
- # # However it is clearly unreasonable and should be rejected.
147
- # client.onopen = lambda {
148
- # client.send_data("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00")
149
- # }
150
- # end
151
- # end
152
- #
153
- # it "should handle impossible frames by calling onerror callback" do
154
- # EM.run do
155
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
156
- # server.onerror { |error|
157
- # error.should be_an_instance_of EM::WebSocket::DataError
158
- # error.message.should == "Invalid frame received"
159
- # EM.stop
160
- # }
161
- # }
162
- #
163
- # # Create a fake client which sends draft 76 handshake
164
- # client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
165
- # client.send_data(format_request(@request))
166
- #
167
- # client.onopen = lambda {
168
- # client.send_data("foobar") # Does not start with \x00 or \xff
169
- # }
170
- # end
171
- # end
172
- #
173
- # it "should handle invalid http requests by raising HandshakeError passed to onerror callback" do
174
- # EM.run {
175
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
176
- # server.onerror { |error|
177
- # error.should be_an_instance_of EM::WebSocket::HandshakeError
178
- # error.message.should == "Invalid HTTP header"
179
- # EM.stop
180
- # }
181
- # }
182
- #
183
- # client = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
184
- # client.send_data("This is not a HTTP header\r\n\r\n")
185
- # }
186
- # end
187
- #
188
- # it "should handle handshake request split into two TCP packets" do
189
- # EM.run do
190
- # EM.add_timer(0.1) do
191
- # EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
192
- #
193
- # # Create a fake client which sends draft 76 handshake
194
- # connection = EM.connect('0.0.0.0', 12345, FakeWebSocketClient)
195
- # data = format_request(@request)
196
- # # Sends first half of the request
197
- # connection.send_data(data[0...(data.length / 2)])
198
- #
199
- # connection.onopen = lambda {
200
- # connection.handshake_response.lines.sort.
201
- # should == format_response(@response).lines.sort
202
- # EM.stop
203
- # }
204
- #
205
- # EM.add_timer(0.1) do
206
- # # Sends second half of the request
207
- # connection.send_data(data[(data.length / 2)..-1])
208
- # end
209
- # end
210
- # end
211
- # end
212
- # end
@@ -1,108 +0,0 @@
1
- require 'helper'
2
-
3
- describe Rack::WebSocket::Framing03 do
4
- class FramingContainer
5
- include Rack::WebSocket::Framing03
6
-
7
- def <<(data)
8
- @data << data
9
- process_data(data)
10
- end
11
-
12
- def debug(*args); end
13
- end
14
-
15
- before :each do
16
- @f = FramingContainer.new
17
- @f.initialize_framing
18
- end
19
-
20
- describe "basic examples" do
21
- it "connection close" do
22
- @f.should_receive(:message).with(:close, '', '')
23
- @f << 0b00000001
24
- @f << 0b00000000
25
- end
26
-
27
- it "ping" do
28
- @f.should_receive(:message).with(:ping, '', '')
29
- @f << 0b00000010
30
- @f << 0b00000000
31
- end
32
-
33
- it "pong" do
34
- @f.should_receive(:message).with(:pong, '', '')
35
- @f << 0b00000011
36
- @f << 0b00000000
37
- end
38
-
39
- it "text" do
40
- @f.should_receive(:message).with(:text, '', 'foo')
41
- @f << 0b00000100
42
- @f << 0b00000011
43
- @f << 'foo'
44
- end
45
-
46
- it "Text in two frames" do
47
- @f.should_receive(:message).with(:text, '', 'hello world')
48
- @f << 0b10000100
49
- @f << 0b00000110
50
- @f << "hello "
51
- @f << 0b00000000
52
- @f << 0b00000101
53
- @f << "world"
54
- end
55
-
56
- it "2 byte extended payload length text frame" do
57
- data = 'a' * 256
58
- @f.should_receive(:message).with(:text, '', data)
59
- @f << 0b00000100 # Single frame, text
60
- @f << 0b01111110 # Length 126 (so read 2 bytes)
61
- @f << 0b00000001 # Two bytes in network byte order (256)
62
- @f << 0b00000000
63
- @f << data
64
- end
65
- end
66
-
67
- # These examples are straight from the spec
68
- # http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6
69
- describe "examples from the spec" do
70
- it "a single-frame text message" do
71
- @f.should_receive(:message).with(:text, '', 'Hello')
72
- @f << "\x04\x05Hello"
73
- end
74
-
75
- it "a fragmented text message" do
76
- @f.should_receive(:message).with(:text, '', 'Hello')
77
- @f << "\x84\x03Hel"
78
- @f << "\x00\x02lo"
79
- end
80
-
81
- it "Ping request and response" do
82
- @f.should_receive(:message).with(:ping, '', 'Hello')
83
- @f << "\x02\x05Hello"
84
- end
85
-
86
- it "256 bytes binary message in a single frame" do
87
- data = "a"*256
88
- @f.should_receive(:message).with(:binary, '', data)
89
- @f << "\x05\x7E\x01\x00" + data
90
- end
91
-
92
- it "64KiB binary message in a single frame" do
93
- data = "a"*65536
94
- @f.should_receive(:message).with(:binary, '', data)
95
- @f << "\x05\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data
96
- end
97
- end
98
-
99
- describe "error cases" do
100
- it "should raise an exception on continuation frame without preceeding more frame" do
101
- lambda {
102
- @f << 0b00000000 # Single frame, continuation
103
- @f << 0b00000001 # Length 1
104
- @f << 'f'
105
- }.should raise_error(Rack::WebSocket::WebSocketError, 'Continuation frame not expected')
106
- end
107
- end
108
- end