async-websocket 0.14.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/async/websocket/adapters/http.rb +64 -0
- data/lib/async/websocket/adapters/rack.rb +11 -28
- data/{spec/async/websocket/upgrade.rb → lib/async/websocket/adapters/rails.rb} +20 -19
- data/lib/async/websocket/client.rb +19 -13
- data/lib/async/websocket/connect_request.rb +4 -0
- data/lib/async/websocket/connection.rb +1 -0
- data/lib/async/websocket/version.rb +1 -1
- metadata +37 -101
- data/.editorconfig +0 -6
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.travis.yml +0 -21
- data/Gemfile +0 -7
- data/README.md +0 -143
- data/async-websocket.gemspec +0 -29
- data/examples/chat/.env +0 -3
- data/examples/chat/README.md +0 -147
- data/examples/chat/client.rb +0 -32
- data/examples/chat/config.ru +0 -150
- data/examples/chat/multi-client.rb +0 -79
- data/examples/mud/client.rb +0 -34
- data/examples/mud/config.ru +0 -142
- data/examples/rack/client.rb +0 -19
- data/examples/rack/config.ru +0 -12
- data/examples/utopia/.bowerrc +0 -4
- data/examples/utopia/.gitignore +0 -9
- data/examples/utopia/.rspec +0 -4
- data/examples/utopia/Gemfile +0 -33
- data/examples/utopia/Guardfile +0 -29
- data/examples/utopia/README.md +0 -16
- data/examples/utopia/Rakefile +0 -8
- data/examples/utopia/config.ru +0 -47
- data/examples/utopia/config/README.md +0 -7
- data/examples/utopia/config/environment.rb +0 -8
- data/examples/utopia/lib/readme.txt +0 -1
- data/examples/utopia/pages/_heading.xnode +0 -2
- data/examples/utopia/pages/_page.xnode +0 -30
- data/examples/utopia/pages/client/client.js +0 -28
- data/examples/utopia/pages/client/index.xnode +0 -8
- data/examples/utopia/pages/errors/exception.xnode +0 -5
- data/examples/utopia/pages/errors/file-not-found.xnode +0 -5
- data/examples/utopia/pages/links.yaml +0 -2
- data/examples/utopia/pages/server/controller.rb +0 -26
- data/examples/utopia/public/_static/icon.png +0 -0
- data/examples/utopia/public/_static/site.css +0 -205
- data/examples/utopia/public/_static/utopia-background.svg +0 -1
- data/examples/utopia/public/_static/utopia.svg +0 -1
- data/examples/utopia/public/readme.txt +0 -1
- data/examples/utopia/spec/spec_helper.rb +0 -31
- data/examples/utopia/spec/website_context.rb +0 -11
- data/examples/utopia/spec/website_spec.rb +0 -56
- data/examples/utopia/tasks/bower.rake +0 -45
- data/examples/utopia/tasks/deploy.rake +0 -13
- data/examples/utopia/tasks/development.rake +0 -34
- data/examples/utopia/tasks/environment.rake +0 -17
- data/examples/utopia/tasks/log.rake +0 -17
- data/examples/utopia/tasks/static.rake +0 -43
- data/spec/async/websocket/adapters/rack/client.rb +0 -38
- data/spec/async/websocket/adapters/rack/config.ru +0 -23
- data/spec/async/websocket/adapters/rack_spec.rb +0 -84
- data/spec/async/websocket/connection_spec.rb +0 -34
- data/spec/async/websocket/server_examples.rb +0 -117
- data/spec/async/websocket/server_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -16
@@ -1,45 +0,0 @@
|
|
1
|
-
|
2
|
-
namespace :bower do
|
3
|
-
desc 'Load the .bowerrc file and setup the environment for other tasks.'
|
4
|
-
task :bowerrc do
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
bowerrc_path = SITE_ROOT + ".bowerrc"
|
8
|
-
bowerrc = JSON.load(File.read(bowerrc_path))
|
9
|
-
|
10
|
-
@bower_package_root = SITE_ROOT + bowerrc['directory']
|
11
|
-
@bower_install_root = SITE_ROOT + bowerrc['public']
|
12
|
-
@bower_install_method = (bowerrc['install'] || :copy).to_sym
|
13
|
-
end
|
14
|
-
|
15
|
-
desc 'Update the bower packages and link into the public directory.'
|
16
|
-
task :update => :bowerrc do
|
17
|
-
require 'fileutils'
|
18
|
-
require 'utopia/path'
|
19
|
-
|
20
|
-
#sh %W{bower update}
|
21
|
-
|
22
|
-
@bower_package_root.children.select(&:directory?).collect(&:basename).each do |package_directory|
|
23
|
-
install_path = @bower_install_root + package_directory
|
24
|
-
package_path = @bower_package_root + package_directory
|
25
|
-
dist_path = package_path + 'dist'
|
26
|
-
|
27
|
-
FileUtils::Verbose.rm_rf install_path
|
28
|
-
FileUtils::Verbose.mkpath(install_path.dirname)
|
29
|
-
|
30
|
-
# If a package has a dist directory, we only symlink that... otherwise we have to do the entire package, and hope that bower's ignore was setup correctly:
|
31
|
-
if File.exist? dist_path
|
32
|
-
link_path = Utopia::Path.shortest_path(dist_path, install_path)
|
33
|
-
else
|
34
|
-
link_path = Utopia::Path.shortest_path(package_path, install_path)
|
35
|
-
end
|
36
|
-
|
37
|
-
if @bower_install_method == :symlink
|
38
|
-
# This is useful for some
|
39
|
-
FileUtils::Verbose.ln_s link_path, install_path
|
40
|
-
else
|
41
|
-
FileUtils::Verbose.cp_r File.expand_path(link_path, install_path), install_path
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
|
2
|
-
desc 'Run by git post-update hook when deployed to a web server'
|
3
|
-
task :deploy do
|
4
|
-
# This task is typiclly run after the site is updated but before the server is restarted.
|
5
|
-
end
|
6
|
-
|
7
|
-
desc 'Restart the application server'
|
8
|
-
task :restart do
|
9
|
-
# This task is run after the deployment task above.
|
10
|
-
if passenger_config = `which passenger-config`.chomp!
|
11
|
-
sh(passenger_config, 'restart-app', '--ignore-passenger-not-running', SITE_ROOT.to_s)
|
12
|
-
end
|
13
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
|
2
|
-
require "rspec/core/rake_task"
|
3
|
-
|
4
|
-
RSpec::Core::RakeTask.new(:test) do |task|
|
5
|
-
task.rspec_opts = %w{--require simplecov} if ENV['COVERAGE']
|
6
|
-
end
|
7
|
-
|
8
|
-
task :coverage do
|
9
|
-
ENV['COVERAGE'] = 'y'
|
10
|
-
end
|
11
|
-
|
12
|
-
desc 'Start the development server.'
|
13
|
-
task :server => :environment do
|
14
|
-
exec('guard', '-g', 'development')
|
15
|
-
end
|
16
|
-
|
17
|
-
desc 'Start the development environment which includes web server and tests.'
|
18
|
-
task :development => :environment do
|
19
|
-
exec('guard', '-g', 'development,test')
|
20
|
-
end
|
21
|
-
|
22
|
-
desc 'Start an interactive console for your web application'
|
23
|
-
task :console => :environment do
|
24
|
-
require 'pry'
|
25
|
-
require 'rack/test'
|
26
|
-
|
27
|
-
include Rack::Test::Methods
|
28
|
-
|
29
|
-
def app
|
30
|
-
@app ||= Rack::Builder.parse_file(SITE_ROOT + 'config.ru').first
|
31
|
-
end
|
32
|
-
|
33
|
-
Pry.start
|
34
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
|
2
|
-
desc 'Set up the environment for running your web application'
|
3
|
-
task :environment do |task|
|
4
|
-
require SITE_ROOT + 'config/environment'
|
5
|
-
|
6
|
-
# We ensure this is part of the shell environment so if other commands are invoked they will work correctly.
|
7
|
-
ENV['RACK_ENV'] = RACK_ENV.to_s if defined?(RACK_ENV)
|
8
|
-
ENV['DATABASE_ENV'] = DATABASE_ENV.to_s if defined?(DATABASE_ENV)
|
9
|
-
|
10
|
-
# This generates a consistent session secret if one was not already provided:
|
11
|
-
if ENV['UTOPIA_SESSION_SECRET'].nil?
|
12
|
-
require 'securerandom'
|
13
|
-
|
14
|
-
warn 'Generating transient session key for development...'
|
15
|
-
ENV['UTOPIA_SESSION_SECRET'] = SecureRandom.hex(32)
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
|
2
|
-
task :log do
|
3
|
-
require 'utopia/logger'
|
4
|
-
LOGGER = Utopia::Logger.new
|
5
|
-
end
|
6
|
-
|
7
|
-
namespace :log do
|
8
|
-
desc "Increase verbosity of logger to info."
|
9
|
-
task :info => :log do
|
10
|
-
LOGGER.level = Logger::INFO
|
11
|
-
end
|
12
|
-
|
13
|
-
desc "Increase verbosity of global debug."
|
14
|
-
task :debug => :log do
|
15
|
-
LOGGER.level = Logger::DEBUG
|
16
|
-
end
|
17
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
|
2
|
-
namespace :static do
|
3
|
-
task :static_environment do
|
4
|
-
RACK_ENV ||= :static
|
5
|
-
DATABASE_ENV ||= :production
|
6
|
-
SERVER_PORT ||= 9291
|
7
|
-
end
|
8
|
-
|
9
|
-
desc "Generate a static copy of the site."
|
10
|
-
task :generate => [:static_environment, :environment] do
|
11
|
-
require 'falcon/server'
|
12
|
-
require 'async/io'
|
13
|
-
require 'async/container'
|
14
|
-
|
15
|
-
config_path = SITE_ROOT + 'config.ru'
|
16
|
-
container_class = Async::Container::Threaded
|
17
|
-
|
18
|
-
app, options = Rack::Builder.parse_file(config_path.to_s)
|
19
|
-
|
20
|
-
container = container_class.new(concurrency: 2) do
|
21
|
-
server = Falcon::Server.new(app, [
|
22
|
-
Async::IO::Endpoint.parse("tcp://localhost:#{SERVER_PORT}", reuse_port: true)
|
23
|
-
])
|
24
|
-
|
25
|
-
server.run
|
26
|
-
end
|
27
|
-
|
28
|
-
output_path = ENV.fetch('OUTPUT_PATH') {SITE_ROOT + 'static'}
|
29
|
-
|
30
|
-
# Delete any existing stuff:
|
31
|
-
FileUtils.rm_rf(output_path)
|
32
|
-
|
33
|
-
# Copy all public assets:
|
34
|
-
Dir.glob(SITE_ROOT + 'public/*').each do |path|
|
35
|
-
FileUtils.cp_r(path, output_path)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Generate HTML pages:
|
39
|
-
system("wget", "--mirror", "--recursive", "--continue", "--convert-links", "--adjust-extension", "--no-host-directories", "--directory-prefix", output_path.to_s, "http://localhost:#{SERVER_PORT}")
|
40
|
-
|
41
|
-
container.stop
|
42
|
-
end
|
43
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/io/stream'
|
5
|
-
require 'async/http/endpoint'
|
6
|
-
require 'async/websocket/client'
|
7
|
-
|
8
|
-
USER = ARGV.pop || "anonymous"
|
9
|
-
URL = ARGV.pop || "http://localhost:7070"
|
10
|
-
|
11
|
-
Async do |task|
|
12
|
-
stdin = Async::IO::Stream.new(
|
13
|
-
Async::IO::Generic.new($stdin)
|
14
|
-
)
|
15
|
-
|
16
|
-
endpoint = Async::HTTP::Endpoint.parse(URL)
|
17
|
-
headers = {'token' => 'wubalubadubdub'}
|
18
|
-
|
19
|
-
Async::WebSocket::Client.open(endpoint, headers: headers) do |connection|
|
20
|
-
input_task = task.async do
|
21
|
-
while line = stdin.read_until("\n")
|
22
|
-
connection.write({user: USER, text: line})
|
23
|
-
connection.flush
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
connection.write({
|
28
|
-
user: USER,
|
29
|
-
status: "connected",
|
30
|
-
})
|
31
|
-
|
32
|
-
while message = connection.read
|
33
|
-
puts message.inspect
|
34
|
-
end
|
35
|
-
ensure
|
36
|
-
input_task&.stop
|
37
|
-
end
|
38
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
#!/usr/bin/env -S falcon serve --bind http://localhost:7070 --count 1 -c
|
2
|
-
|
3
|
-
require 'async/websocket/adapters/rack'
|
4
|
-
require 'set'
|
5
|
-
|
6
|
-
$connections = Set.new
|
7
|
-
|
8
|
-
run lambda {|env|
|
9
|
-
Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
|
10
|
-
$connections << connection
|
11
|
-
|
12
|
-
begin
|
13
|
-
while message = connection.read
|
14
|
-
$connections.each do |connection|
|
15
|
-
connection.write(message)
|
16
|
-
connection.flush
|
17
|
-
end
|
18
|
-
end
|
19
|
-
ensure
|
20
|
-
$connections.delete(connection)
|
21
|
-
end
|
22
|
-
end or [200, {}, ["Hello World"]]
|
23
|
-
}
|
@@ -1,84 +0,0 @@
|
|
1
|
-
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
require 'async/websocket'
|
22
|
-
require 'async/websocket/client'
|
23
|
-
require 'async/websocket/adapters/rack'
|
24
|
-
|
25
|
-
require 'rack/test'
|
26
|
-
require 'falcon/server'
|
27
|
-
require 'falcon/adapters/rack'
|
28
|
-
require 'async/http/endpoint'
|
29
|
-
|
30
|
-
RSpec.describe Async::WebSocket::Adapters::Rack do
|
31
|
-
include_context Async::RSpec::Reactor
|
32
|
-
|
33
|
-
let(:endpoint) {Async::HTTP::Endpoint.parse("http://localhost:7050")}
|
34
|
-
let(:app) {Rack::Builder.parse_file(File.expand_path('rack/config.ru', __dir__)).first}
|
35
|
-
let(:server) {Falcon::Server.new(Falcon::Server.middleware(app), endpoint)}
|
36
|
-
let(:client) {Async::HTTP::Client.new(endpoint)}
|
37
|
-
|
38
|
-
let!(:server_task) do
|
39
|
-
reactor.async do
|
40
|
-
server.run
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
after do
|
45
|
-
server_task.stop
|
46
|
-
end
|
47
|
-
|
48
|
-
it "can make non-websocket connection to server" do
|
49
|
-
response = client.get("/")
|
50
|
-
|
51
|
-
expect(response).to be_success
|
52
|
-
expect(response.read).to be == "Hello World"
|
53
|
-
|
54
|
-
client.close
|
55
|
-
end
|
56
|
-
|
57
|
-
let(:message) do
|
58
|
-
{text: "Hello World"}
|
59
|
-
end
|
60
|
-
|
61
|
-
it "can make websocket connection to server" do
|
62
|
-
Async::WebSocket::Client.connect(endpoint) do |connection|
|
63
|
-
connection.write(message)
|
64
|
-
|
65
|
-
expect(connection.read).to be == message
|
66
|
-
|
67
|
-
connection.close
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should use mask over insecure connection" do
|
72
|
-
expect(endpoint).to_not be_secure
|
73
|
-
|
74
|
-
Async::WebSocket::Client.connect(endpoint) do |connection|
|
75
|
-
expect(connection.mask).to_not be_nil
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should negotiate protocol" do
|
80
|
-
Async::WebSocket::Client.connect(endpoint, protocols: ['ws']) do |connection|
|
81
|
-
expect(connection.protocol).to be == 'ws'
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
require 'async/websocket/connection'
|
22
|
-
|
23
|
-
RSpec.describe Async::WebSocket::Connection do
|
24
|
-
let(:framer) {double}
|
25
|
-
subject {described_class.new(framer)}
|
26
|
-
|
27
|
-
it "should use mask if specified" do
|
28
|
-
expect(framer).to receive(:write_frame) do |frame|
|
29
|
-
expect(frame.mask).to be == subject.mask
|
30
|
-
end
|
31
|
-
|
32
|
-
subject.write({text: "Hello World"})
|
33
|
-
end
|
34
|
-
end
|
@@ -1,117 +0,0 @@
|
|
1
|
-
# Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
require 'async/websocket/client'
|
22
|
-
require 'async/websocket/server'
|
23
|
-
|
24
|
-
require 'async/http/client'
|
25
|
-
require 'async/http/server'
|
26
|
-
require 'async/http/endpoint'
|
27
|
-
|
28
|
-
RSpec.shared_context Async::WebSocket::Server do
|
29
|
-
include_context Async::RSpec::Reactor
|
30
|
-
|
31
|
-
let(:protocol) {described_class}
|
32
|
-
let(:endpoint) {Async::HTTP::Endpoint.parse('http://127.0.0.1:8008')}
|
33
|
-
|
34
|
-
let!(:client) {Async::WebSocket::Client.open(endpoint, protocol)}
|
35
|
-
|
36
|
-
let!(:server_task) do
|
37
|
-
reactor.async do
|
38
|
-
server.run
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
after(:each) do
|
43
|
-
Async.logger.debug(client, "Closing client...")
|
44
|
-
client.close
|
45
|
-
Async.logger.debug(server_task, "Closing server...")
|
46
|
-
server_task.stop
|
47
|
-
end
|
48
|
-
|
49
|
-
let(:handler) {Async::WebSocket::Connection}
|
50
|
-
let(:headers) {Array.new}
|
51
|
-
|
52
|
-
let(:message) {["Hello World"]}
|
53
|
-
|
54
|
-
let(:server) do
|
55
|
-
Async::HTTP::Server.for(endpoint, protocol) do |request|
|
56
|
-
if Async::WebSocket::Request.websocket?(request)
|
57
|
-
Async::WebSocket::Response.for(request, headers) do |stream|
|
58
|
-
framer = Protocol::WebSocket::Framer.new(stream)
|
59
|
-
|
60
|
-
connection = handler.call(framer)
|
61
|
-
|
62
|
-
connection.write(message)
|
63
|
-
|
64
|
-
connection.close
|
65
|
-
end
|
66
|
-
else
|
67
|
-
Protocol::HTTP::Response[404, {}, []]
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
it "can establish connection" do
|
73
|
-
connection = client.connect("/server")
|
74
|
-
|
75
|
-
begin
|
76
|
-
expect(connection.read).to be == message
|
77
|
-
expect(connection.read).to be_nil
|
78
|
-
expect(connection).to be_closed
|
79
|
-
ensure
|
80
|
-
connection.close
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context "with headers" do
|
85
|
-
let(:headers) {{"foo" => "bar"}}
|
86
|
-
|
87
|
-
let(:server) do
|
88
|
-
Async::HTTP::Server.for(endpoint, protocol) do |request|
|
89
|
-
if Async::WebSocket::Request.websocket?(request)
|
90
|
-
Async::WebSocket::Response.for(request, headers) do |stream|
|
91
|
-
framer = Protocol::WebSocket::Framer.new(stream)
|
92
|
-
|
93
|
-
connection = handler.call(framer)
|
94
|
-
|
95
|
-
connection.write(request.headers.fields)
|
96
|
-
|
97
|
-
connection.close
|
98
|
-
end
|
99
|
-
else
|
100
|
-
Protocol::HTTP::Response[404, {}, []]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
it "can send headers" do
|
106
|
-
connection = client.connect("/headers", headers: headers)
|
107
|
-
|
108
|
-
begin
|
109
|
-
expect(connection.read.to_h).to include(*headers.keys)
|
110
|
-
expect(connection.read).to be_nil
|
111
|
-
expect(connection).to be_closed
|
112
|
-
ensure
|
113
|
-
connection.close
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|