isomorfeus-transport 1.0.0.delta7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e31570f39250ea91f27fdc953fa0658868e4d56d7cd848483431863acf005d1a
4
+ data.tar.gz: 2d00bbef87e55ff8f5873f3faf603b55c48cb0ac874970f2fccd4bf8978b2dc0
5
+ SHA512:
6
+ metadata.gz: cffbfe276aaf67746cb3f6ec0e8b47333169d0fc60b278cc034bef2ed3684d536dcfffd8038905aa2b97c16ac7bbf8cd6b9db25c9dfc25a4f063acc17be61dac
7
+ data.tar.gz: 667055f7067f7aef78ae133556e75d930ac4782c787b517e5db964834c2e8e0a6998c275de00687a6dbe0823a6463a6fd87d2131486a6a5a2963f7af9e436b9a
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Jan Biedermann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # isomorfeus-transport
2
+
3
+ Transport and PubSub for isomorfeus.
4
+
5
+ ### Community and Support
6
+ At the [Isomorfeus Framework Project](http://isomorfeus.com)
7
+
8
+ ## Installation
9
+ isomorfeus-transport is usually installed with the installer.
10
+ Otherwise add to your Gemfile:
11
+ ```ruby
12
+ gem 'isomorfeus-transport'
13
+ ```
14
+ and bundle install/update
15
+
16
+ ## Server Side Rendering
17
+ `yarn add ws`
18
+
19
+ The 'ws' module then needs to be imported in application_ssr.js:
20
+ ```
21
+ import WebSocket from 'ws';
22
+ global.WebSocket = WebSocket;
23
+ ```
24
+
25
+ ## Configuration options
26
+
27
+ Client and Server:
28
+ - Isomorfeus.api_websocket_path - path for server side endpoint, default: `/isomorfeus/api/websocket`
29
+
30
+ Server only:
31
+ - Isomorfeus.middlewares - all the rack middlewares to load
32
+
33
+
34
+ ## LucidChannel
35
+
36
+ Isomorfeus-transport provides the LucidChannel::Mixin and LucidChannel::Base class.
37
+ These can be used for subscriptions and publishing messages.
38
+
39
+ ### Subscriptions
40
+ ```ruby
41
+ class MyChannel < LucidChannel::Base
42
+ end
43
+
44
+ # subscribe to channel
45
+ MyChannel.subscribe
46
+
47
+ # unsubscribe
48
+ MyChannel.unsubscribe
49
+ ```
50
+
51
+ ### Processing messages
52
+ ```ruby
53
+ class MyChannel < LucidChannel::Base
54
+ on_message do |message|
55
+ puts "received: " + message
56
+ end
57
+ end
58
+ ```
59
+
60
+ ### Sending mesages
61
+ ```ruby
62
+ MyChannel.send_message('uiuiui')
63
+ ```
@@ -0,0 +1,44 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ require 'json'
3
+ require 'isomorfeus/config'
4
+ require 'isomorfeus/execution_environment'
5
+ require 'isomorfeus/transport/version'
6
+ require 'isomorfeus/transport/config'
7
+ require 'isomorfeus/transport/request_agent'
8
+ require 'isomorfeus/transport/client_processor'
9
+ require 'isomorfeus/transport/websocket'
10
+ require 'isomorfeus/transport'
11
+ require 'lucid_channel/mixin'
12
+ require 'lucid_channel/base'
13
+ Isomorfeus::Transport.init!
14
+ else
15
+ require 'base64'
16
+ require 'digest'
17
+ require 'socket'
18
+ require 'oj'
19
+ require 'websocket/driver'
20
+ require 'active_support'
21
+ require 'iodine'
22
+ require 'isomorfeus/config'
23
+ require 'isomorfeus/promise'
24
+ require 'isomorfeus/transport/version'
25
+ require 'isomorfeus/transport/config'
26
+ require 'isomorfeus/transport/middlewares'
27
+ require 'isomorfeus/transport/request_agent'
28
+ require 'isomorfeus/transport/server_processor'
29
+ require 'isomorfeus/transport/server_socket_processor'
30
+ require 'isomorfeus/transport/websocket'
31
+ require 'isomorfeus/handler'
32
+ require 'isomorfeus/transport/rack_middleware'
33
+ Opal.append_path(__dir__.untaint) unless Opal.paths.include?(__dir__.untaint)
34
+
35
+ require 'isomorfeus/transport/middlewares'
36
+
37
+ Isomorfeus.add_middleware(Isomorfeus::Transport::RackMiddleware)
38
+
39
+ if Dir.exist?(File.join('app', 'isomorfeus'))
40
+ $LOAD_PATH.unshift(File.expand_path(File.join('app', 'isomorfeus', 'handlers')))
41
+ elsif Dir.exist?(File.join('isomorfeus'))
42
+ $LOAD_PATH.unshift(File.expand_path(File.join('isomorfeus', 'handlers')))
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ module Isomorfeus
2
+ module Handler
3
+ # for autoloader
4
+ end
5
+ end
@@ -0,0 +1,141 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ class << self
4
+ attr_accessor :socket
5
+
6
+ def delay(ms = 1000, &block)
7
+ `setTimeout(#{block.to_n}, ms)`
8
+ end
9
+
10
+ def init!
11
+ @requests_in_progress = { requests: {}, agent_ids: {} }
12
+ @socket = nil
13
+ connect if Isomorfeus.on_browser?
14
+ end
15
+
16
+ def connect
17
+ return if @socket && @socket.ready_state < 2
18
+ if Isomorfeus.on_browser?
19
+ window_protocol = `window.location.protocol`
20
+ ws_protocol = window_protocol == 'https:' ? 'wss:' : 'ws:'
21
+ ws_url = "#{ws_protocol}#{`window.location.host`}#{Isomorfeus.api_websocket_path}"
22
+ else
23
+ ws_url = Isomorfeus::TopLevel.transport_ws_url
24
+ end
25
+ @socket = Isomorfeus::Transport::Websocket.new(ws_url)
26
+ @socket.on_error do
27
+ @socket.close
28
+ delay do
29
+ Isomorfeus::Transport.connect
30
+ end
31
+ end
32
+ @socket.on_message do |event|
33
+ json_hash = `Opal.Hash.$new(JSON.parse(event.data))`
34
+ Isomorfeus::Transport::ClientProcessor.process(json_hash)
35
+ end
36
+ true
37
+ end
38
+
39
+ def disconnect
40
+ @socket.close if @socket
41
+ @socket = nil
42
+ end
43
+
44
+ def promise_send_path(*path, &block)
45
+ request = {}
46
+ path.inject(request) do |memo, key|
47
+ memo[key] = {}
48
+ end
49
+ Isomorfeus::Transport.promise_send_request(request, &block)
50
+ end
51
+
52
+ def promise_send_request(request, &block)
53
+ if request_in_progress?(request)
54
+ agent = get_agent_for_request_in_progress(request)
55
+ else
56
+ agent = Isomorfeus::Transport::RequestAgent.new(request)
57
+ if block_given?
58
+ agent.promise.then do |response|
59
+ block.call(response)
60
+ end
61
+ end
62
+ register_request_in_progress(request, agent.id)
63
+ @socket.send(`JSON.stringify(#{{request: { agent_ids: { agent.id => request }}}.to_n})`)
64
+ end
65
+ agent.promise
66
+ end
67
+
68
+ def send_notification(processor_class, message)
69
+ @socket.send(`JSON.stringify(#{{notification: { class: processor_class.to_s, message: message}}.to_n})`)
70
+ true
71
+ end
72
+
73
+ def subscribe(processor_class, &block)
74
+ request = { subscribe: true, class: processor_class.to_s }
75
+ if request_in_progress?(request)
76
+ agent = get_agent_for_request_in_progress(request)
77
+ else
78
+ agent = Isomorfeus::Transport::RequestAgent.new(request)
79
+ register_request_in_progress(request, agent.id)
80
+ @socket.send(`JSON.stringify(#{{subscribe: { agent_ids: { agent.id => request }}}.to_n})`)
81
+ end
82
+ result_promise = agent.promise.then do |response|
83
+ response[:agent_response]
84
+ end
85
+ if block_given?
86
+ result_promise = result_promise.then do |response|
87
+ block.call(response)
88
+ end
89
+ end
90
+ result_promise
91
+ end
92
+
93
+ def unsubscribe(processor_class, &block)
94
+ request = { unsubscribe: true, class: processor_class.to_s }
95
+ if request_in_progress?(request)
96
+ agent = get_agent_for_request_in_progress(request)
97
+ else
98
+ agent = Isomorfeus::Transport::RequestAgent.new(request)
99
+ register_request_in_progress(request, agent.id)
100
+ @socket.send(`JSON.stringify(#{{unsubscribe: { agent_ids: { agent.id => request }}}.to_n})`)
101
+ end
102
+ result_promise = agent.promise.then do |response|
103
+ response[:agent_response]
104
+ end
105
+ if block_given?
106
+ result_promise = result_promise.then do |response|
107
+ block.call(response)
108
+ end
109
+ end
110
+ result_promise
111
+ end
112
+
113
+ def busy?
114
+ @requests_in_progress.size != 0
115
+ end
116
+
117
+ def requests_in_progress
118
+ @requests_in_progress
119
+ end
120
+
121
+ def request_in_progress?(request)
122
+ @requests_in_progress[:requests].key?(request)
123
+ end
124
+
125
+ def get_agent_for_request_in_progress(request)
126
+ agent_id = @requests_in_progress[:requests][request]
127
+ Isomorfeus::Transport::RequestAgent.get(agent_id)
128
+ end
129
+
130
+ def register_request_in_progress(request, agent_id)
131
+ @requests_in_progress[:requests][request] = agent_id
132
+ @requests_in_progress[:agent_ids][agent_id] = request
133
+ end
134
+
135
+ def unregister_request_in_progress(agent_id)
136
+ request = @requests_in_progress[:agent_ids].delete(agent_id)
137
+ @requests_in_progress[:requests].delete(request)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,26 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ class ClientProcessor
4
+ def self.process(json_hash)
5
+ if json_hash.key?(:response)
6
+ process_response(json_hash)
7
+ elsif json_hash.key?(:notification)
8
+ process_notification(json_hash)
9
+ end
10
+ end
11
+
12
+ def self.process_notification(notification_hash)
13
+ processor_class = "::#{notification_hash[:notification][:class]}".constantize
14
+ processor_class.process_message(notification_hash[:notification][:message])
15
+ end
16
+
17
+ def self.process_response(response_hash)
18
+ response_hash[:response][:agent_ids].keys.each do |agent_id|
19
+ agent = Isomorfeus::Transport::RequestAgent.get!(agent_id)
20
+ Isomorfeus::Transport.unregister_request_in_progress(agent_id)
21
+ agent.promise.resolve(agent_response: response_hash[:response][:agent_ids][agent_id], full_response: response_hash)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module Isomorfeus
2
+ # available settings
3
+
4
+ if RUBY_ENGINE == 'opal'
5
+ add_client_option(:api_websocket_path)
6
+ else
7
+ # defaults
8
+ class << self
9
+ attr_accessor :api_websocket_path
10
+ attr_accessor :middlewares
11
+
12
+ def add_middleware(middleware)
13
+ Isomorfeus.middlewares << middleware unless Isomorfeus.middlewares.include?(middleware)
14
+ end
15
+
16
+ def insert_middleware_after(existing_middleware, new_middleware)
17
+ index_of_existing = Isomorfeus.middlewares.index(existing_middleware)
18
+ unless Isomorfeus.middlewares.include?(new_middleware)
19
+ if index_of_existing
20
+ Isomorfeus.middlewares.insert(index_of_existing + 1, new_middleware)
21
+ else
22
+ Isomorfeus.middlewares << new_middleware
23
+ end
24
+ end
25
+ end
26
+
27
+ def insert_middleware_before(existing_middleware, new_middleware)
28
+ index_of_existing = Isomorfeus.middlewares.index(existing_middleware)
29
+ unless Isomorfeus.middlewares.include?(new_middleware)
30
+ if index_of_existing
31
+ Isomorfeus.middlewares.insert(index_of_existing, new_middleware)
32
+ else
33
+ Isomorfeus.middlewares << new_middleware
34
+ end
35
+ end
36
+ end
37
+ end
38
+ self.middlewares = Set.new
39
+ end
40
+
41
+ self.api_websocket_path = '/isomorfeus/api/websocket'
42
+ end
@@ -0,0 +1,11 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ module Middlewares
4
+ def use_isomorfeus_middlewares
5
+ Isomorfeus.middlewares.each do |isomorfeus_middleware|
6
+ use isomorfeus_middleware
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Isomorfeus
4
+ module Transport
5
+ class RackMiddleware
6
+ include Isomorfeus::Transport::ServerProcessor
7
+
8
+ WS_RESPONSE = [0, {}, []]
9
+
10
+ def initialize(app)
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ if env['PATH_INFO'] == Isomorfeus.api_websocket_path
16
+ user = defined?(Warden::Manager) ? env['warden'].user : nil
17
+ if env['rack.upgrade?'] == :websocket
18
+ env['rack.upgrade'] = Isomorfeus::Transport::ServerSocketProcessor.new(env['rack.session'], user)
19
+ end
20
+ WS_RESPONSE
21
+ else
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ class RequestAgent
4
+ def self.agents
5
+ @_agents ||= {}
6
+ end
7
+
8
+ def self.get(object_id)
9
+ agents[object_id]
10
+ end
11
+
12
+ def self.get!(object_id)
13
+ agents.delete(object_id.to_s)
14
+ end
15
+
16
+ attr_reader :id
17
+ attr_reader :promise
18
+ attr_reader :request
19
+
20
+ def initialize(request = nil)
21
+ @id = object_id.to_s
22
+ self.class.agents[@id] = self
23
+ @promise = Promise.new
24
+ @request = request
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Isomorfeus
4
+ module Transport
5
+ module ServerProcessor
6
+ def process_request(client, session_id, current_user, request)
7
+ response = { response: { agent_ids: {}} }
8
+
9
+ if request.key?('request') && request['request'].key?('agent_ids')
10
+ request['request']['agent_ids'].keys.each do |agent_id|
11
+ request['request']['agent_ids'][agent_id].keys.each do |key|
12
+ handler = "::#{key.underscore.camelize}Handler".constantize
13
+ if handler
14
+ response[:response][:agent_ids][agent_id] = handler.new.process_request(client, session_id, current_user, request['request']['agent_ids'][agent_id][key], response)
15
+ else
16
+ response[:response][:agent_ids][agent_id] = { error: { key => 'No such handler!'}}
17
+ end
18
+ end
19
+ end
20
+ elsif request.key?('notification')
21
+ if request['notification'].key?('class')
22
+ client.publish(request['notification']['class'], Oj.dump({ 'notification' => request['notification'] }, mode: :strict))
23
+ else
24
+ response[:response] = 'No such thing!'
25
+ end
26
+ elsif request.key?('subscribe') && request['subscribe'].key?('agent_ids')
27
+ agent_id = request['subscribe']['agent_ids'].keys.first
28
+ channel = request['subscribe']['agent_ids'][agent_id]['class']
29
+ if channel
30
+ client.subscribe(channel)
31
+ response[:response][:agent_ids][agent_id] = { success: channel }
32
+ else
33
+ response[:response][:agent_ids][agent_id] = { error: "No such thing!"}
34
+ end
35
+ elsif request.key?('unsubscribe') && request['unsubscribe'].key?('agent_ids')
36
+ agent_id = request['unsubscribe']['agent_ids'].keys.first
37
+ channel = request['unsubscribe']['agent_ids'][agent_id]['class']
38
+ if channel
39
+ client.unsubscribe(channel)
40
+ response[:response][:agent_ids][agent_id] = { success: channel }
41
+ else
42
+ response[:response][:agent_ids][agent_id] = { error: 'No such thing!'}
43
+ end
44
+ else
45
+ response[:response] = 'No such thing!'
46
+ end
47
+ response
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ class ServerSocketProcessor
4
+ include Isomorfeus::Transport::ServerProcessor
5
+
6
+ def initialize(session_id, user)
7
+ @session_id = session_id
8
+ @user = user
9
+ end
10
+
11
+ def on_message(client, data)
12
+ request_hash = Oj.load(data, mode: :strict)
13
+ result = process_request(client, @session_id, @user, request_hash)
14
+ client.write Oj.dump(result, mode: :strict)
15
+ end
16
+
17
+ def on_close(client)
18
+ # nothing for now
19
+ end
20
+
21
+ def on_open(client)
22
+ # nothing for now
23
+ end
24
+
25
+ def on_shutdown(client)
26
+ # nothing for now
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ VERSION = '1.0.0.delta7'
4
+ end
5
+ end
@@ -0,0 +1,115 @@
1
+ module Isomorfeus
2
+ module Transport
3
+ class Websocket
4
+ attr_reader :url
5
+
6
+ if RUBY_ENGINE == 'opal'
7
+ CONNECTING = 0
8
+ OPEN = 1
9
+ CLOSING = 2
10
+ CLOSED = 3
11
+
12
+ class SendError < StandardError; end
13
+
14
+ def initialize(url, protocols = nil)
15
+ @url = url
16
+ @native_websocket = if protocols
17
+ `new Opal.global.WebSocket(url, protocols)`
18
+ else
19
+ `new Opal.global.WebSocket(url)`
20
+ end
21
+ end
22
+
23
+ def close
24
+ @native_websocket.JS.close
25
+ nil
26
+ end
27
+
28
+ def on_close(&block)
29
+ @native_websocket.JS[:onclose] = `function(event) { block.$call(event); }`
30
+ end
31
+
32
+ def on_error(&block)
33
+ @native_websocket.JS[:onerror] = `function(event) { block.$call(event); }`
34
+ end
35
+
36
+ def on_message(&block)
37
+ @native_websocket.JS[:onmessage] = `function(event) { block.$call(event); }`
38
+ end
39
+
40
+ def send(data)
41
+ case ready_state
42
+ when OPEN then @native_websocket.JS.send(data)
43
+ when CONNECTING then Isomorfeus::Transport.delay(50) { send(data) }
44
+ when CLOSING then raise SendError.new('Cant send, connection is closing!')
45
+ when CLOSED then raise SendError.new('Cant send, connection is closed!')
46
+ end
47
+ end
48
+ alias_method :write, :send
49
+
50
+ private
51
+
52
+ def ready_state
53
+ @native_websocket.JS[:readyState]
54
+ end
55
+ else
56
+ def initialize(url, protocols = nil)
57
+ @url = url
58
+ parsed_url = URI.parse(url)
59
+ host = parsed_url.host
60
+ port = parsed_url.port
61
+ @socket = TCPSocket.new(host, port)
62
+ @driver = ::WebSocket::Driver.client(self)
63
+ @driver.on(:close, &method(:internal_on_close))
64
+
65
+ @thread = Thread.new do
66
+ begin
67
+ while data = @sock.readpartial(512)
68
+ @driver.parse(data)
69
+ end
70
+ end
71
+ end
72
+
73
+ @driver.start
74
+ end
75
+
76
+ def close
77
+ @driver.close
78
+ @thread.kill
79
+ end
80
+
81
+ def on_close(&block)
82
+ @on_close_block = block
83
+ end
84
+
85
+ def on_error(&block)
86
+ @driver.on(:error, block)
87
+ end
88
+
89
+ def on_message(&block)
90
+ @on_message_block = block
91
+ end
92
+
93
+ def on_open(&block)
94
+ @driver.on(:open, block)
95
+ end
96
+
97
+ def protocol
98
+ @driver.protocol
99
+ end
100
+
101
+ def send(data)
102
+ @socket.write(data)
103
+ end
104
+ alias_method :write, :send
105
+
106
+ private
107
+
108
+ def internal_on_close(event)
109
+ @on_close_block.call(event)
110
+ @thread.kill
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,5 @@
1
+ module LucidChannel
2
+ class Base
3
+ include LucidChannel::Mixin
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ module LucidChannel
2
+ module Mixin
3
+ def self.included(base)
4
+ base.instance_exec do
5
+ def process_message(message)
6
+ if @message_processor
7
+ @message_processor.call(message)
8
+ else
9
+ puts "#{self} received: #{message}, but no processor defined!"
10
+ end
11
+ end
12
+
13
+ def on_message(&block)
14
+ @message_processor = block
15
+ end
16
+
17
+ def send_message(message)
18
+ Isomorfeus::Transport.send_notification(self, message)
19
+ end
20
+
21
+ def subscribe
22
+ Isomorfeus::Transport.subscribe(self)
23
+ end
24
+
25
+ def unsubscribe
26
+ Isomorfeus::Transport.unsubscribe(self)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: isomorfeus-transport
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.delta7
5
+ platform: ruby
6
+ authors:
7
+ - Jan Biedermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: iodine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.7.32
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.7.32
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: opal
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.11.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.11.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: isomorfeus-redux
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 4.0.7
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 4.0.7
83
+ - !ruby/object:Gem::Dependency
84
+ name: isomorfeus-react
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 16.8.7
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 16.8.7
97
+ - !ruby/object:Gem::Dependency
98
+ name: websocket-driver
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.7.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.7.0
111
+ description: Various transport options for Isomorfeus.
112
+ email: jan@kursator.de
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - LICENSE
118
+ - README.md
119
+ - lib/isomorfeus-transport.rb
120
+ - lib/isomorfeus/handler.rb
121
+ - lib/isomorfeus/transport.rb
122
+ - lib/isomorfeus/transport/client_processor.rb
123
+ - lib/isomorfeus/transport/config.rb
124
+ - lib/isomorfeus/transport/middlewares.rb
125
+ - lib/isomorfeus/transport/rack_middleware.rb
126
+ - lib/isomorfeus/transport/request_agent.rb
127
+ - lib/isomorfeus/transport/server_processor.rb
128
+ - lib/isomorfeus/transport/server_socket_processor.rb
129
+ - lib/isomorfeus/transport/version.rb
130
+ - lib/isomorfeus/transport/websocket.rb
131
+ - lib/lucid_channel/base.rb
132
+ - lib/lucid_channel/mixin.rb
133
+ homepage: http://isomorfeus.com
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">"
149
+ - !ruby/object:Gem::Version
150
+ version: 1.3.1
151
+ requirements: []
152
+ rubygems_version: 3.0.3
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Various transport options for Isomorfeus.
156
+ test_files: []