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,136 +0,0 @@
1
- require 'helper'
2
-
3
- describe "Rack::WebSocket::Handler" 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
- @secure_request = @request.merge(:port => 443)
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
- @secure_response = @response.merge(:headers => @response[:headers].merge('Sec-WebSocket-Location' => "wss://example.com:443/demo"))
33
- end
34
-
35
- it "should handle good request" do
36
- handler(@request).should send_handshake(@response)
37
- end
38
-
39
- it "should handle good request to secure default port if secure mode is enabled" do
40
- handler(@secure_request, true).should send_handshake(@secure_response)
41
- end
42
-
43
- it "should not handle good request to secure default port if secure mode is disabled" do
44
- handler(@secure_request, false).should_not send_handshake(@secure_response)
45
- end
46
-
47
- it "should handle good request on nondefault port" do
48
- @request[:port] = 8081
49
- @request[:headers]['Host'] = 'example.com:8081'
50
- @response[:headers]['Sec-WebSocket-Location'] =
51
- 'ws://example.com:8081/demo'
52
-
53
- handler(@request).should send_handshake(@response)
54
- end
55
-
56
- it "should handle good request to secure nondefault port" do
57
- @secure_request[:port] = 8081
58
- @secure_request[:headers]['Host'] = 'example.com:8081'
59
- @secure_response[:headers]['Sec-WebSocket-Location'] = 'wss://example.com:8081/demo'
60
- handler(@secure_request, true).should send_handshake(@secure_response)
61
- end
62
-
63
- it "should handle good request with no protocol" do
64
- @request[:headers].delete('Sec-WebSocket-Protocol')
65
- @response[:headers].delete("Sec-WebSocket-Protocol")
66
-
67
- handler(@request).should send_handshake(@response)
68
- end
69
-
70
- it "should handle extra headers by simply ignoring them" do
71
- @request[:headers]['EmptyValue'] = ""
72
- @request[:headers]['AKey'] = "AValue"
73
-
74
- handler(@request).should send_handshake(@response)
75
- end
76
-
77
- it "should raise error on HTTP request" do
78
- @request[:headers] = {
79
- 'Host' => 'www.google.com',
80
- 'User-Agent' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 GTB6 GTBA',
81
- 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
82
- 'Accept-Language' => 'en-us,en;q=0.5',
83
- 'Accept-Encoding' => 'gzip,deflate',
84
- 'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
85
- 'Keep-Alive' => '300',
86
- 'Connection' => 'keep-alive',
87
- }
88
-
89
- lambda {
90
- handler(@request).handshake
91
- }.should raise_error(Rack::WebSocket::HandshakeError)
92
- end
93
-
94
- it "should raise error on wrong method" do
95
- @request[:method] = 'POST'
96
-
97
- lambda {
98
- handler(@request).handshake
99
- }.should raise_error(Rack::WebSocket::HandshakeError)
100
- end
101
-
102
- it "should raise error if upgrade header incorrect" do
103
- @request[:headers]['Upgrade'] = 'NonWebSocket'
104
-
105
- lambda {
106
- handler(@request).handshake
107
- }.should raise_error(Rack::WebSocket::HandshakeError)
108
- end
109
-
110
- it "should raise error if Sec-WebSocket-Protocol is empty" do
111
- @request[:headers]['Sec-WebSocket-Protocol'] = ''
112
-
113
- lambda {
114
- handler(@request).handshake
115
- }.should raise_error(Rack::WebSocket::HandshakeError)
116
- end
117
-
118
- %w[Sec-WebSocket-Key1 Sec-WebSocket-Key2].each do |header|
119
- it "should raise error if #{header} has zero spaces" do
120
- @request[:headers][header] = 'nospaces'
121
-
122
- lambda {
123
- handler(@request).handshake
124
- }.should raise_error(Rack::WebSocket::HandshakeError, 'Websocket Key1 or Key2 does not contain spaces - this is a symptom of a cross-protocol attack')
125
- end
126
- end
127
-
128
- it "should raise error if spaces do not divide numbers in Sec-WebSocket-Key* " do
129
- @request[:headers]['Sec-WebSocket-Key2'] = '12998 5 Y3 1.P00'
130
-
131
- lambda {
132
- handler(@request).handshake
133
- }.should raise_error(Rack::WebSocket::HandshakeError, 'Invalid Key "12998 5 Y3 1.P00"')
134
- end
135
-
136
- end
@@ -1,210 +0,0 @@
1
- # require 'helper'
2
- #
3
- # describe Rack::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