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