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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/websocket/adapters/http.rb +64 -0
  3. data/lib/async/websocket/adapters/rack.rb +11 -28
  4. data/{spec/async/websocket/upgrade.rb → lib/async/websocket/adapters/rails.rb} +20 -19
  5. data/lib/async/websocket/client.rb +19 -13
  6. data/lib/async/websocket/connect_request.rb +4 -0
  7. data/lib/async/websocket/connection.rb +1 -0
  8. data/lib/async/websocket/version.rb +1 -1
  9. metadata +37 -101
  10. data/.editorconfig +0 -6
  11. data/.gitignore +0 -13
  12. data/.rspec +0 -3
  13. data/.travis.yml +0 -21
  14. data/Gemfile +0 -7
  15. data/README.md +0 -143
  16. data/async-websocket.gemspec +0 -29
  17. data/examples/chat/.env +0 -3
  18. data/examples/chat/README.md +0 -147
  19. data/examples/chat/client.rb +0 -32
  20. data/examples/chat/config.ru +0 -150
  21. data/examples/chat/multi-client.rb +0 -79
  22. data/examples/mud/client.rb +0 -34
  23. data/examples/mud/config.ru +0 -142
  24. data/examples/rack/client.rb +0 -19
  25. data/examples/rack/config.ru +0 -12
  26. data/examples/utopia/.bowerrc +0 -4
  27. data/examples/utopia/.gitignore +0 -9
  28. data/examples/utopia/.rspec +0 -4
  29. data/examples/utopia/Gemfile +0 -33
  30. data/examples/utopia/Guardfile +0 -29
  31. data/examples/utopia/README.md +0 -16
  32. data/examples/utopia/Rakefile +0 -8
  33. data/examples/utopia/config.ru +0 -47
  34. data/examples/utopia/config/README.md +0 -7
  35. data/examples/utopia/config/environment.rb +0 -8
  36. data/examples/utopia/lib/readme.txt +0 -1
  37. data/examples/utopia/pages/_heading.xnode +0 -2
  38. data/examples/utopia/pages/_page.xnode +0 -30
  39. data/examples/utopia/pages/client/client.js +0 -28
  40. data/examples/utopia/pages/client/index.xnode +0 -8
  41. data/examples/utopia/pages/errors/exception.xnode +0 -5
  42. data/examples/utopia/pages/errors/file-not-found.xnode +0 -5
  43. data/examples/utopia/pages/links.yaml +0 -2
  44. data/examples/utopia/pages/server/controller.rb +0 -26
  45. data/examples/utopia/public/_static/icon.png +0 -0
  46. data/examples/utopia/public/_static/site.css +0 -205
  47. data/examples/utopia/public/_static/utopia-background.svg +0 -1
  48. data/examples/utopia/public/_static/utopia.svg +0 -1
  49. data/examples/utopia/public/readme.txt +0 -1
  50. data/examples/utopia/spec/spec_helper.rb +0 -31
  51. data/examples/utopia/spec/website_context.rb +0 -11
  52. data/examples/utopia/spec/website_spec.rb +0 -56
  53. data/examples/utopia/tasks/bower.rake +0 -45
  54. data/examples/utopia/tasks/deploy.rake +0 -13
  55. data/examples/utopia/tasks/development.rake +0 -34
  56. data/examples/utopia/tasks/environment.rake +0 -17
  57. data/examples/utopia/tasks/log.rake +0 -17
  58. data/examples/utopia/tasks/static.rake +0 -43
  59. data/spec/async/websocket/adapters/rack/client.rb +0 -38
  60. data/spec/async/websocket/adapters/rack/config.ru +0 -23
  61. data/spec/async/websocket/adapters/rack_spec.rb +0 -84
  62. data/spec/async/websocket/connection_spec.rb +0 -34
  63. data/spec/async/websocket/server_examples.rb +0 -117
  64. data/spec/async/websocket/server_spec.rb +0 -31
  65. 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