websocket-rack 0.1.4 → 0.2.1

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