em-websocket 0.3.8 → 0.4.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.
@@ -36,6 +36,8 @@ describe "draft03" do
36
36
  end
37
37
 
38
38
  it_behaves_like "a websocket server" do
39
+ let(:version) { 3 }
40
+
39
41
  def start_server
40
42
  EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
41
43
  yield ws
@@ -32,6 +32,8 @@ describe "draft13" do
32
32
  end
33
33
 
34
34
  it_behaves_like "a websocket server" do
35
+ let(:version) { 13 }
36
+
35
37
  def start_server
36
38
  EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
37
39
  yield ws
@@ -10,6 +10,8 @@ describe "WebSocket server draft75" do
10
10
  default_timeout 1
11
11
 
12
12
  it_behaves_like "a websocket server" do
13
+ let(:version) { 75 }
14
+
13
15
  def start_server
14
16
  EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
15
17
  yield ws
@@ -108,7 +110,7 @@ describe "WebSocket server draft75" do
108
110
  ws.onclose { EventMachine.stop }
109
111
  ws.onerror {|e|
110
112
  e.should be_an_instance_of EventMachine::WebSocket::HandshakeError
111
- e.message.should match('Connection and Upgrade headers required')
113
+ e.message.should match('Not an upgrade request')
112
114
  EventMachine.stop
113
115
  }
114
116
  end
@@ -35,6 +35,8 @@ describe "WebSocket server draft76" do
35
35
  end
36
36
 
37
37
  it_behaves_like "a websocket server" do
38
+ let(:version) { 76 }
39
+
38
40
  def start_server
39
41
  EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
40
42
  yield ws
@@ -185,7 +187,7 @@ describe "WebSocket server draft76" do
185
187
  EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
186
188
  server.onerror { |error|
187
189
  error.should be_an_instance_of EM::WebSocket::HandshakeError
188
- error.message.should == "Invalid HTTP header"
190
+ error.message.should == "Invalid HTTP header: Could not parse data entirely"
189
191
  done
190
192
  }
191
193
  }
@@ -3,6 +3,32 @@
3
3
  # These tests are run against all draft versions
4
4
  #
5
5
  shared_examples_for "a websocket server" do
6
+ it "should expose the protocol version" do
7
+ em {
8
+ start_server { |ws|
9
+ ws.onopen { |handshake|
10
+ handshake.protocol_version.should == version
11
+ done
12
+ }
13
+ }
14
+
15
+ start_client
16
+ }
17
+ end
18
+
19
+ it "should expose the origin header" do
20
+ em {
21
+ start_server { |ws|
22
+ ws.onopen { |handshake|
23
+ handshake.origin.should == 'http://example.com'
24
+ done
25
+ }
26
+ }
27
+
28
+ start_client
29
+ }
30
+ end
31
+
6
32
  it "should call onerror if an application error raised in onopen" do
7
33
  em {
8
34
  start_server { |ws|
@@ -1,11 +1,12 @@
1
1
  require 'helper'
2
2
 
3
- describe "EventMachine::WebSocket::Handler" do
4
- def handler(request, secure = false)
5
- connection = Object.new
6
- EM::WebSocket::HandlerFactory.build(connection, format_request(request), secure)
3
+ describe EM::WebSocket::Handshake do
4
+ def handshake(request, secure = false)
5
+ handshake = EM::WebSocket::Handshake.new(secure)
6
+ handshake.receive_data(format_request(request))
7
+ handshake
7
8
  end
8
-
9
+
9
10
  before :each do
10
11
  @request = {
11
12
  :port => 80,
@@ -36,47 +37,51 @@ describe "EventMachine::WebSocket::Handler" do
36
37
  }
37
38
  @secure_response = @response.merge(:headers => @response[:headers].merge('Sec-WebSocket-Location' => "wss://example.com/demo"))
38
39
  end
39
-
40
+
40
41
  it "should handle good request" do
41
- handler(@request).should send_handshake(@response)
42
+ handshake(@request).should succeed_with_upgrade(@response)
42
43
  end
43
-
44
+
44
45
  it "should handle good request to secure default port if secure mode is enabled" do
45
- handler(@secure_request, true).should send_handshake(@secure_response)
46
+ handshake(@secure_request, true).
47
+ should succeed_with_upgrade(@secure_response)
46
48
  end
47
-
49
+
48
50
  it "should not handle good request to secure default port if secure mode is disabled" do
49
- handler(@secure_request, false).should_not send_handshake(@secure_response)
51
+ handshake(@secure_request, false).
52
+ should_not succeed_with_upgrade(@secure_response)
50
53
  end
51
-
54
+
52
55
  it "should handle good request on nondefault port" do
53
56
  @request[:port] = 8081
54
57
  @request[:headers]['Host'] = 'example.com:8081'
55
58
  @response[:headers]['Sec-WebSocket-Location'] =
56
59
  'ws://example.com:8081/demo'
57
60
 
58
- handler(@request).should send_handshake(@response)
61
+ handshake(@request).should succeed_with_upgrade(@response)
59
62
  end
60
-
63
+
61
64
  it "should handle good request to secure nondefault port" do
62
65
  @secure_request[:port] = 8081
63
66
  @secure_request[:headers]['Host'] = 'example.com:8081'
64
67
  @secure_response[:headers]['Sec-WebSocket-Location'] = 'wss://example.com:8081/demo'
65
- handler(@secure_request, true).should send_handshake(@secure_response)
68
+
69
+ handshake(@secure_request, true).
70
+ should succeed_with_upgrade(@secure_response)
66
71
  end
67
-
72
+
68
73
  it "should handle good request with no protocol" do
69
74
  @request[:headers].delete('Sec-WebSocket-Protocol')
70
75
  @response[:headers].delete("Sec-WebSocket-Protocol")
71
76
 
72
- handler(@request).should send_handshake(@response)
77
+ handshake(@request).should succeed_with_upgrade(@response)
73
78
  end
74
-
79
+
75
80
  it "should handle extra headers by simply ignoring them" do
76
81
  @request[:headers]['EmptyValue'] = ""
77
82
  @request[:headers]['AKey'] = "AValue"
78
83
 
79
- handler(@request).should send_handshake(@response)
84
+ handshake(@request).should succeed_with_upgrade(@response)
80
85
  end
81
86
 
82
87
  it "should raise error on HTTP request" do
@@ -91,69 +96,98 @@ describe "EventMachine::WebSocket::Handler" do
91
96
  'Connection' => 'keep-alive',
92
97
  }
93
98
 
94
- lambda {
95
- handler(@request).handshake
96
- }.should raise_error(EM::WebSocket::HandshakeError)
99
+ handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError)
97
100
  end
98
-
101
+
99
102
  it "should raise error on wrong method" do
100
103
  @request[:method] = 'POST'
101
104
 
102
- lambda {
103
- handler(@request).handshake
104
- }.should raise_error(EM::WebSocket::HandshakeError)
105
+ handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError)
105
106
  end
106
-
107
+
107
108
  it "should raise error if upgrade header incorrect" do
108
109
  @request[:headers]['Upgrade'] = 'NonWebSocket'
109
110
 
110
- lambda {
111
- handler(@request).handshake
112
- }.should raise_error(EM::WebSocket::HandshakeError)
111
+ handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError)
113
112
  end
114
-
113
+
115
114
  it "should raise error if Sec-WebSocket-Protocol is empty" do
116
115
  @request[:headers]['Sec-WebSocket-Protocol'] = ''
117
116
 
118
- lambda {
119
- handler(@request).handshake
120
- }.should raise_error(EM::WebSocket::HandshakeError)
117
+ handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError)
121
118
  end
122
-
119
+
123
120
  %w[Sec-WebSocket-Key1 Sec-WebSocket-Key2].each do |header|
124
121
  it "should raise error if #{header} has zero spaces" do
125
122
  @request[:headers][header] = 'nospaces'
126
123
 
127
- lambda {
128
- handler(@request).handshake
129
- }.should raise_error(EM::WebSocket::HandshakeError, 'Websocket Key1 or Key2 does not contain spaces - this is a symptom of a cross-protocol attack')
124
+ handshake(@request).
125
+ should fail_with_error(EM::WebSocket::HandshakeError, 'Websocket Key1 or Key2 does not contain spaces - this is a symptom of a cross-protocol attack')
130
126
  end
131
127
  end
132
-
128
+
133
129
  it "should raise error if spaces do not divide numbers in Sec-WebSocket-Key* " do
134
130
  @request[:headers]['Sec-WebSocket-Key2'] = '12998 5 Y3 1.P00'
135
131
 
136
- lambda {
137
- handler(@request).handshake
138
- }.should raise_error(EM::WebSocket::HandshakeError, 'Invalid Key "12998 5 Y3 1.P00"')
132
+ handshake(@request).
133
+ should fail_with_error(EM::WebSocket::HandshakeError, 'Invalid Key "12998 5 Y3 1.P00"')
139
134
  end
140
-
135
+
141
136
  it "should raise error if the HTTP header is empty" do
142
- connection = Object.new
143
- lambda {
144
- EM::WebSocket::HandlerFactory.build(connection, "\r\n\r\nfoobar", false)
145
- }.should raise_error(EM::WebSocket::HandshakeError, "Empty HTTP header")
137
+ handshake = EM::WebSocket::Handshake.new(false)
138
+ handshake.receive_data("\r\n\r\nfoobar")
139
+
140
+ handshake.
141
+ should fail_with_error(EM::WebSocket::HandshakeError, 'Invalid HTTP header: Could not parse data entirely')
146
142
  end
147
143
 
148
- it "should leave request with incomplete header" do
149
- data = format_request(@request)
150
- # Sends only half of the request
151
- EM::WebSocket::HandlerFactory.build(mock(EM::WebSocket::Connection), data[0...(data.length / 2)]).should == nil
152
- end
144
+ # This might seems crazy, but very occasionally we saw multiple "Upgrade:
145
+ # WebSocket" headers in the wild. RFC 4.2.1 isn't particularly clear on this
146
+ # point, so for now I have decided not to accept --@mloughran
147
+ it "should raise error on multiple upgrade headers" do
148
+ handshake = EM::WebSocket::Handshake.new(false)
149
+
150
+ # Add a duplicate upgrade header
151
+ headers = format_request(@request)
152
+ upgrade_header = "Upgrade: WebSocket\r\n"
153
+ headers.gsub!(upgrade_header, "#{upgrade_header}#{upgrade_header}")
154
+
155
+ handshake.receive_data(headers)
153
156
 
154
- it "should leave request with incomplete third key" do
155
- data = format_request(@request)
157
+ handshake.errback { |e|
158
+ e.class.should == EM::WebSocket::HandshakeError
159
+ e.message.should == 'Invalid upgrade header: ["WebSocket", "WebSocket"]'
160
+ }
161
+ end
162
+
163
+ it "should cope with requests where the header is split" do
164
+ request = format_request(@request)
165
+ incomplete_request = request[0...(request.length / 2)]
166
+ rest = request[(request.length / 2)..-1]
167
+ handshake = EM::WebSocket::Handshake.new(false)
168
+ handshake.receive_data(incomplete_request)
169
+
170
+ handshake.instance_variable_get(:@deferred_status).should == nil
171
+
172
+ # Send the remaining header
173
+ handshake.receive_data(rest)
174
+
175
+ handshake(@request).should succeed_with_upgrade(@response)
176
+ end
177
+
178
+ it "should cope with requests where the third key is split" do
179
+ request = format_request(@request)
156
180
  # Removes last two bytes of the third key
157
- EM::WebSocket::HandlerFactory.build(mock(EM::WebSocket::Connection), data[0...(data.length - 2)]).should == nil
181
+ incomplete_request = request[0..-3]
182
+ rest = request[-2..-1]
183
+ handshake = EM::WebSocket::Handshake.new(false)
184
+ handshake.receive_data(incomplete_request)
185
+
186
+ handshake.instance_variable_get(:@deferred_status).should == nil
187
+
188
+ # Send the remaining third key
189
+ handshake.receive_data(rest)
190
+
191
+ handshake(@request).should succeed_with_upgrade(@response)
158
192
  end
159
193
  end
metadata CHANGED
@@ -1,144 +1,137 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: em-websocket
3
- version: !ruby/object:Gem::Version
4
- hash: 3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 3
9
- - 8
10
- version: 0.3.8
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Ilya Grigorik
14
9
  - Martyn Loughran
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2012-07-12 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2013-01-22 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: eventmachine
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 61
30
- segments:
31
- - 0
32
- - 12
33
- - 9
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
34
22
  version: 0.12.9
35
23
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: addressable
39
24
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 0.12.9
31
+ - !ruby/object:Gem::Dependency
32
+ name: http_parser.rb
33
+ requirement: !ruby/object:Gem::Requirement
41
34
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 9
46
- segments:
47
- - 2
48
- - 1
49
- - 1
50
- version: 2.1.1
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 0.5.3
51
39
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: em-spec
55
40
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
57
42
  none: false
58
- requirements:
43
+ requirements:
59
44
  - - ~>
60
- - !ruby/object:Gem::Version
61
- hash: 27
62
- segments:
63
- - 0
64
- - 2
65
- - 6
45
+ - !ruby/object:Gem::Version
46
+ version: 0.5.3
47
+ - !ruby/object:Gem::Dependency
48
+ name: em-spec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
66
54
  version: 0.2.6
67
55
  type: :development
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: eventmachine
71
56
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
57
+ version_requirements: !ruby/object:Gem::Requirement
73
58
  none: false
74
- requirements:
59
+ requirements:
75
60
  - - ~>
76
- - !ruby/object:Gem::Version
77
- hash: 59
78
- segments:
79
- - 0
80
- - 12
81
- - 10
82
- version: 0.12.10
61
+ - !ruby/object:Gem::Version
62
+ version: 0.2.6
63
+ - !ruby/object:Gem::Dependency
64
+ name: eventmachine
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
83
71
  type: :development
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: em-http-request
87
72
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
73
+ version_requirements: !ruby/object:Gem::Requirement
89
74
  none: false
90
- requirements:
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: em-http-request
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
91
84
  - - ~>
92
- - !ruby/object:Gem::Version
93
- hash: 27
94
- segments:
95
- - 0
96
- - 2
97
- - 6
85
+ - !ruby/object:Gem::Version
98
86
  version: 0.2.6
99
87
  type: :development
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: rspec
103
88
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: 0.2.6
95
+ - !ruby/object:Gem::Dependency
96
+ name: rspec
97
+ requirement: !ruby/object:Gem::Requirement
105
98
  none: false
106
- requirements:
99
+ requirements:
107
100
  - - ~>
108
- - !ruby/object:Gem::Version
109
- hash: 47
110
- segments:
111
- - 2
112
- - 8
113
- - 0
114
- version: 2.8.0
101
+ - !ruby/object:Gem::Version
102
+ version: 2.12.0
115
103
  type: :development
116
- version_requirements: *id006
117
- - !ruby/object:Gem::Dependency
118
- name: rake
119
104
  prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 2.12.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
121
114
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 3
126
- segments:
127
- - 0
128
- version: "0"
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
129
119
  type: :development
130
- version_requirements: *id007
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
131
127
  description: EventMachine based WebSocket server
132
- email:
128
+ email:
133
129
  - ilya@igvita.com
134
130
  - me@mloughran.com
135
131
  executables: []
136
-
137
132
  extensions: []
138
-
139
133
  extra_rdoc_files: []
140
-
141
- files:
134
+ files:
142
135
  - .gitignore
143
136
  - CHANGELOG.rdoc
144
137
  - Gemfile
@@ -146,11 +139,6 @@ files:
146
139
  - Rakefile
147
140
  - em-websocket.gemspec
148
141
  - examples/echo.rb
149
- - examples/flash_policy_file_server.rb
150
- - examples/js/FABridge.js
151
- - examples/js/WebSocketMain.swf
152
- - examples/js/swfobject.js
153
- - examples/js/web_socket.js
154
142
  - examples/multicast.rb
155
143
  - examples/ping.rb
156
144
  - examples/test.html
@@ -175,7 +163,7 @@ files:
175
163
  - lib/em-websocket/handler13.rb
176
164
  - lib/em-websocket/handler75.rb
177
165
  - lib/em-websocket/handler76.rb
178
- - lib/em-websocket/handler_factory.rb
166
+ - lib/em-websocket/handshake.rb
179
167
  - lib/em-websocket/handshake04.rb
180
168
  - lib/em-websocket/handshake75.rb
181
169
  - lib/em-websocket/handshake76.rb
@@ -194,42 +182,39 @@ files:
194
182
  - spec/integration/draft76_spec.rb
195
183
  - spec/integration/shared_examples.rb
196
184
  - spec/unit/framing_spec.rb
197
- - spec/unit/handler_spec.rb
185
+ - spec/unit/handshake_spec.rb
198
186
  - spec/unit/masking_spec.rb
199
187
  homepage: http://github.com/igrigorik/em-websocket
200
188
  licenses: []
201
-
202
189
  post_install_message:
203
190
  rdoc_options: []
204
-
205
- require_paths:
191
+ require_paths:
206
192
  - lib
207
- required_ruby_version: !ruby/object:Gem::Requirement
193
+ required_ruby_version: !ruby/object:Gem::Requirement
208
194
  none: false
209
- requirements:
210
- - - ">="
211
- - !ruby/object:Gem::Version
212
- hash: 3
213
- segments:
195
+ requirements:
196
+ - - ! '>='
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ segments:
214
200
  - 0
215
- version: "0"
216
- required_rubygems_version: !ruby/object:Gem::Requirement
201
+ hash: 3969961455966824026
202
+ required_rubygems_version: !ruby/object:Gem::Requirement
217
203
  none: false
218
- requirements:
219
- - - ">="
220
- - !ruby/object:Gem::Version
221
- hash: 3
222
- segments:
204
+ requirements:
205
+ - - ! '>='
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ segments:
223
209
  - 0
224
- version: "0"
210
+ hash: 3969961455966824026
225
211
  requirements: []
226
-
227
212
  rubyforge_project: em-websocket
228
- rubygems_version: 1.8.6
213
+ rubygems_version: 1.8.24
229
214
  signing_key:
230
215
  specification_version: 3
231
216
  summary: EventMachine based WebSocket server
232
- test_files:
217
+ test_files:
233
218
  - spec/helper.rb
234
219
  - spec/integration/common_spec.rb
235
220
  - spec/integration/draft03_spec.rb
@@ -240,5 +225,5 @@ test_files:
240
225
  - spec/integration/draft76_spec.rb
241
226
  - spec/integration/shared_examples.rb
242
227
  - spec/unit/framing_spec.rb
243
- - spec/unit/handler_spec.rb
228
+ - spec/unit/handshake_spec.rb
244
229
  - spec/unit/masking_spec.rb