websocket-rack 0.1.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.
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.md +105 -0
- data/Rakefile +11 -0
- data/example/example.ru +31 -0
- data/example/html/FABridge.js +604 -0
- data/example/html/WebSocketMain.swf +0 -0
- data/example/html/index.html +76 -0
- data/example/html/swfobject.js +4 -0
- data/example/html/web_socket.js +388 -0
- data/lib/rack/websocket/application.rb +65 -0
- data/lib/rack/websocket/connection.rb +105 -0
- data/lib/rack/websocket/debugger.rb +17 -0
- data/lib/rack/websocket/extensions/thin/connection.rb +71 -0
- data/lib/rack/websocket/extensions/thin.rb +16 -0
- data/lib/rack/websocket/framing03.rb +178 -0
- data/lib/rack/websocket/framing76.rb +115 -0
- data/lib/rack/websocket/handler.rb +43 -0
- data/lib/rack/websocket/handler03.rb +14 -0
- data/lib/rack/websocket/handler75.rb +8 -0
- data/lib/rack/websocket/handler76.rb +11 -0
- data/lib/rack/websocket/handler_factory.rb +61 -0
- data/lib/rack/websocket/handshake75.rb +21 -0
- data/lib/rack/websocket/handshake76.rb +71 -0
- data/lib/rack/websocket.rb +40 -0
- data/spec/helper.rb +44 -0
- data/spec/integration/draft03_spec.rb +252 -0
- data/spec/integration/draft76_spec.rb +212 -0
- data/spec/unit/framing_spec.rb +108 -0
- data/spec/unit/handler_spec.rb +136 -0
- data/spec/websocket_spec.rb +210 -0
- data/websocket-rack.gemspec +23 -0
- metadata +147 -0
@@ -0,0 +1,210 @@
|
|
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
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rack/websocket"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "websocket-rack"
|
7
|
+
s.version = Rack::WebSocket::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Bernard Potocki"]
|
10
|
+
s.email = ["bernard.potocki@imanel.org"]
|
11
|
+
s.homepage = "http://github.com/imanel/websocket-rack"
|
12
|
+
s.summary = %q{Rack-based WebSocket server}
|
13
|
+
s.description = %q{Rack-based WebSocket server}
|
14
|
+
|
15
|
+
s.add_dependency 'rack'
|
16
|
+
s.add_dependency 'thin'
|
17
|
+
s.add_development_dependency 'rspec', '~> 2.4.0'
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: websocket-rack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Bernard Potocki
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-05 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rack
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: thin
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 31
|
58
|
+
segments:
|
59
|
+
- 2
|
60
|
+
- 4
|
61
|
+
- 0
|
62
|
+
version: 2.4.0
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
description: Rack-based WebSocket server
|
66
|
+
email:
|
67
|
+
- bernard.potocki@imanel.org
|
68
|
+
executables: []
|
69
|
+
|
70
|
+
extensions: []
|
71
|
+
|
72
|
+
extra_rdoc_files: []
|
73
|
+
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- Gemfile
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- example/example.ru
|
80
|
+
- example/html/FABridge.js
|
81
|
+
- example/html/WebSocketMain.swf
|
82
|
+
- example/html/index.html
|
83
|
+
- example/html/swfobject.js
|
84
|
+
- example/html/web_socket.js
|
85
|
+
- lib/rack/websocket.rb
|
86
|
+
- lib/rack/websocket/application.rb
|
87
|
+
- lib/rack/websocket/connection.rb
|
88
|
+
- lib/rack/websocket/debugger.rb
|
89
|
+
- lib/rack/websocket/extensions/thin.rb
|
90
|
+
- lib/rack/websocket/extensions/thin/connection.rb
|
91
|
+
- lib/rack/websocket/framing03.rb
|
92
|
+
- lib/rack/websocket/framing76.rb
|
93
|
+
- lib/rack/websocket/handler.rb
|
94
|
+
- lib/rack/websocket/handler03.rb
|
95
|
+
- lib/rack/websocket/handler75.rb
|
96
|
+
- lib/rack/websocket/handler76.rb
|
97
|
+
- lib/rack/websocket/handler_factory.rb
|
98
|
+
- lib/rack/websocket/handshake75.rb
|
99
|
+
- lib/rack/websocket/handshake76.rb
|
100
|
+
- spec/helper.rb
|
101
|
+
- spec/integration/draft03_spec.rb
|
102
|
+
- spec/integration/draft76_spec.rb
|
103
|
+
- spec/unit/framing_spec.rb
|
104
|
+
- spec/unit/handler_spec.rb
|
105
|
+
- spec/websocket_spec.rb
|
106
|
+
- websocket-rack.gemspec
|
107
|
+
has_rdoc: true
|
108
|
+
homepage: http://github.com/imanel/websocket-rack
|
109
|
+
licenses: []
|
110
|
+
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
requirements: []
|
135
|
+
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.4.2
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: Rack-based WebSocket server
|
141
|
+
test_files:
|
142
|
+
- spec/helper.rb
|
143
|
+
- spec/integration/draft03_spec.rb
|
144
|
+
- spec/integration/draft76_spec.rb
|
145
|
+
- spec/unit/framing_spec.rb
|
146
|
+
- spec/unit/handler_spec.rb
|
147
|
+
- spec/websocket_spec.rb
|