async-websocket 0.13.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/websocket/adapters/rack.rb +7 -1
  3. data/lib/async/websocket/client.rb +39 -17
  4. data/lib/async/websocket/connect_request.rb +35 -17
  5. data/lib/async/websocket/connect_response.rb +2 -2
  6. data/lib/async/websocket/connection.rb +21 -2
  7. data/lib/async/websocket/request.rb +1 -1
  8. data/lib/async/websocket/response.rb +1 -1
  9. data/lib/async/websocket/server.rb +2 -0
  10. data/lib/async/websocket/upgrade_request.rb +9 -9
  11. data/lib/async/websocket/upgrade_response.rb +3 -3
  12. data/lib/async/websocket/version.rb +1 -1
  13. metadata +35 -102
  14. data/.editorconfig +0 -6
  15. data/.gitignore +0 -13
  16. data/.rspec +0 -3
  17. data/.travis.yml +0 -18
  18. data/Gemfile +0 -12
  19. data/README.md +0 -129
  20. data/Rakefile +0 -6
  21. data/async-websocket.gemspec +0 -29
  22. data/examples/chat/client.rb +0 -32
  23. data/examples/chat/config.ru +0 -113
  24. data/examples/chat/multi-client.rb +0 -81
  25. data/examples/mud/client.rb +0 -34
  26. data/examples/mud/config.ru +0 -142
  27. data/examples/rack/client.rb +0 -20
  28. data/examples/rack/config.ru +0 -14
  29. data/examples/utopia/.bowerrc +0 -4
  30. data/examples/utopia/.gitignore +0 -9
  31. data/examples/utopia/.rspec +0 -4
  32. data/examples/utopia/Gemfile +0 -33
  33. data/examples/utopia/Guardfile +0 -29
  34. data/examples/utopia/README.md +0 -16
  35. data/examples/utopia/Rakefile +0 -8
  36. data/examples/utopia/config.ru +0 -47
  37. data/examples/utopia/config/README.md +0 -7
  38. data/examples/utopia/config/environment.rb +0 -8
  39. data/examples/utopia/lib/readme.txt +0 -1
  40. data/examples/utopia/pages/_heading.xnode +0 -2
  41. data/examples/utopia/pages/_page.xnode +0 -30
  42. data/examples/utopia/pages/client/client.js +0 -28
  43. data/examples/utopia/pages/client/index.xnode +0 -8
  44. data/examples/utopia/pages/errors/exception.xnode +0 -5
  45. data/examples/utopia/pages/errors/file-not-found.xnode +0 -5
  46. data/examples/utopia/pages/links.yaml +0 -2
  47. data/examples/utopia/pages/server/controller.rb +0 -26
  48. data/examples/utopia/public/_static/icon.png +0 -0
  49. data/examples/utopia/public/_static/site.css +0 -205
  50. data/examples/utopia/public/_static/utopia-background.svg +0 -1
  51. data/examples/utopia/public/_static/utopia.svg +0 -1
  52. data/examples/utopia/public/readme.txt +0 -1
  53. data/examples/utopia/spec/spec_helper.rb +0 -31
  54. data/examples/utopia/spec/website_context.rb +0 -11
  55. data/examples/utopia/spec/website_spec.rb +0 -56
  56. data/examples/utopia/tasks/bower.rake +0 -45
  57. data/examples/utopia/tasks/deploy.rake +0 -13
  58. data/examples/utopia/tasks/development.rake +0 -34
  59. data/examples/utopia/tasks/environment.rake +0 -17
  60. data/examples/utopia/tasks/log.rake +0 -17
  61. data/examples/utopia/tasks/static.rake +0 -43
  62. data/spec/async/websocket/adapters/rack/client.rb +0 -38
  63. data/spec/async/websocket/adapters/rack/config.ru +0 -23
  64. data/spec/async/websocket/adapters/rack_spec.rb +0 -84
  65. data/spec/async/websocket/client_spec.rb +0 -48
  66. data/spec/async/websocket/connection_spec.rb +0 -34
  67. data/spec/async/websocket/server_examples.rb +0 -76
  68. data/spec/async/websocket/server_spec.rb +0 -31
  69. data/spec/async/websocket/upgrade.rb +0 -43
  70. data/spec/spec_helper.rb +0 -16
@@ -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,48 +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/response"
23
-
24
- RSpec.describe Async::WebSocket::Client do
25
- describe '#connect' do
26
- let(:headers) {[
27
- ["Foo", "Bar"],
28
- ["Baz", "Qux"]
29
- ]}
30
-
31
- let(:client) {double}
32
- let(:stream) {double}
33
-
34
- subject {described_class.new(client)}
35
- let(:response) {Protocol::HTTP::Response.new(nil, 101, {}, nil, Protocol::WebSocket::Headers::PROTOCOL)}
36
-
37
- it "sets client request headers" do
38
- expect(response).to receive(:stream?).and_return(true)
39
- expect(response).to receive(:stream).and_return(stream)
40
-
41
- expect(client).to receive(:call) do |request|
42
- expect(request.headers.to_h).to include("Foo", "Baz")
43
- end.and_return(response)
44
-
45
- subject.connect("/server", headers: headers)
46
- end
47
- end
48
- 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,76 +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', reuse_port: true)}
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(:server) do
53
- Async::HTTP::Server.for(endpoint, protocol) do |request|
54
- if Async::WebSocket::Request.websocket?(request)
55
- Async::WebSocket::Response.for(request, headers) do |stream|
56
- framer = Protocol::WebSocket::Framer.new(stream)
57
-
58
- connection = handler.call(framer)
59
-
60
- connection.close
61
- end
62
- else
63
- Protocol::HTTP::Response[404, {}, []]
64
- end
65
- end
66
- end
67
-
68
- it "can establish connection" do
69
- connection = client.connect("/server")
70
-
71
- expect(connection.read).to be_nil
72
- expect(connection).to be_closed
73
-
74
- connection.close
75
- end
76
- end
@@ -1,31 +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_relative "server_examples"
22
-
23
- require "async/http/protocol/http1"
24
-
25
- RSpec.describe Async::HTTP::Protocol::HTTP1 do
26
- include_context Async::WebSocket::Server
27
- end
28
-
29
- RSpec.describe Async::HTTP::Protocol::HTTP2 do
30
- include_context Async::WebSocket::Server
31
- end
@@ -1,43 +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/adapters/rack'
22
-
23
- class Upgrade
24
- def initialize(app)
25
- @app = app
26
- end
27
-
28
- def call(env)
29
- Async::WebSocket::Adapters::Rack.open(env, supported_protocols: ['ws']) do |connection|
30
- read, write = IO.pipe
31
-
32
- Process.spawn("ls -lah", :out => write)
33
- write.close
34
-
35
- read.each_line do |line|
36
- connection.write({line: line})
37
- end
38
-
39
- # Gracefully close the connection:
40
- connection.close
41
- end or @app.call(env)
42
- end
43
- end