plezi 0.11.2 → 0.12.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.
@@ -3,19 +3,19 @@ module Plezi
3
3
 
4
4
  module_function
5
5
 
6
- # Defers any missing methods to the GReactor Library.
6
+ # Defers any missing methods to the Iodine Library.
7
7
  def method_missing name, *args, &block
8
8
  return super unless REACTOR_METHODS.include? name
9
- ::GReactor.send name, *args, &block
9
+ ::Iodine.__send__ name, *args, &block
10
10
  end
11
- # Defers any missing methods to the GReactor Library.
11
+ # Defers any missing methods to the Iodine Library.
12
12
  def respond_to_missing?(name, include_private = false)
13
13
  REACTOR_METHODS.include?(name) || super
14
14
  end
15
15
 
16
16
  protected
17
17
 
18
- REACTOR_METHODS = ::GReactor.public_methods(false)
18
+ REACTOR_METHODS = ::Iodine.public_methods(false)
19
19
 
20
20
  end
21
21
 
@@ -3,22 +3,24 @@ PL = Plezi
3
3
 
4
4
  unless defined? PLEZI_NON_DSL
5
5
 
6
- # shortcut for Plezi.listen.
6
+ # shortcut for Plezi.listen. Deprecated.
7
7
  #
8
8
  def listen(params = {})
9
9
  Plezi.listen params
10
10
  end
11
11
 
12
- # adds a virtul host to the current service (the last `listen` call) or switches to an existing host within the active service.
12
+ # adds a virtul host or switches to an existing host, for routes setup or parameters update.
13
13
  #
14
14
  # accepts:
15
15
  # host_name: a String with the full host name (i.e. "www.google.com" / "mail.google.com")
16
- # params:: any of the parameters accepted by the `listen` command, except `protocol`, `handler`, and `ssl` parameters.
16
+ # params:: any of the parameters accepted by the {Plezi.host} command.
17
+ #
18
+ # If no host is specified or host name is `false`, the default host would be set as the active host and returned.
17
19
  def host(host_name = false, params = {})
18
20
  Plezi.host host_name, params
19
21
  end
20
22
 
21
- # adds a route to the last server object
23
+ # adds a route to the last (or default) host
22
24
  #
23
25
  # path:: the path for the route
24
26
  # controller:: The controller class which will accept the route.
@@ -49,7 +51,7 @@ unless defined? PLEZI_NON_DSL
49
51
  #
50
52
  # magic routes make for difficult debugging - the smarter the routes, the more difficult the debugging.
51
53
  # use with care and avoid complex routes when possible. RESTful routes are recommended when possible.
52
- # json serving apps are advised to use required parameters, empty sections indicating missing required parameters (i.e. /path///foo/bar///).
54
+ # JSON serving apps are advised to use required parameters and empty sections indicating missing required parameters (i.e. /path///foo/bar///).
53
55
  #
54
56
  def route(path, controller = nil, &block)
55
57
  Plezi.route(path, controller, &block)
@@ -74,28 +76,10 @@ unless defined? PLEZI_NON_DSL
74
76
  end
75
77
 
76
78
 
77
-
78
- # finishes setup of the servers and starts them up. This will hange the proceess.
79
- #
80
- # this method is called automatically by the Plezi framework.
81
- #
82
- # it is recommended that you DO NOT CALL this method.
83
- # if any post shut-down actions need to be performed, use Plezi.on_shutdown instead.
84
- def start_services
85
- return 0 if defined?(NO_PLEZI_AUTO_START)
86
- undef listen
87
- undef host
88
- undef route
89
- undef shared_route
90
- Plezi.start
91
- end
92
-
93
79
  # sets information to be used when restarting
94
80
  $PL_SCRIPT = $0
95
81
  $PL_ARGV = $*.dup
96
82
 
97
- # sets up a generic session-token name based on the script name
98
- GRHttp.session_token = "#{($0).split(/[\\\/]/).last.split(/[\s\.]+/).first}_uuid"
99
83
  # restarts the Plezi app with the same arguments as when it was started.
100
84
  #
101
85
  # EXPERIMENTAL
@@ -104,5 +88,10 @@ unless defined? PLEZI_NON_DSL
104
88
  end
105
89
 
106
90
  # sets to start the services once dsl script is finished loading.
107
- at_exit { start_services }
91
+ at_exit do
92
+ undef listen
93
+ undef host
94
+ undef route
95
+ undef shared_route
96
+ end
108
97
  end
@@ -24,18 +24,18 @@ module Plezi
24
24
  next if data[:server] == Plezi::Settings.uuid
25
25
  data[:type] = Object.const_get(data[:type]) unless data[:type].nil? || data[:type] == :all
26
26
  if data[:target]
27
- GRHttp::Base::WSHandler.unicast data[:target], data
27
+ data[:type].___faild_unicast( data ) unless Iodine::Http::Websockets.unicast data[:target], data
28
28
  else
29
- GRHttp::Base::WSHandler.broadcast data
29
+ Iodine::Http::Websockets.broadcast data
30
30
  end
31
31
  rescue => e
32
- GReactor.error "The following could be a security breach attempt:"
33
- GReactor.error e
32
+ Iodine.error "The following could be a security breach attempt:"
33
+ Iodine.error e
34
34
  end
35
35
  end
36
36
  end
37
37
  rescue => e
38
- GReactor.error e
38
+ Iodine.error e
39
39
  retry
40
40
  end
41
41
  end
@@ -46,6 +46,10 @@ module Plezi
46
46
  return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis
47
47
  inner_init_redis
48
48
  end
49
+ def away? server
50
+ return true unless get_redis
51
+ @redis.pubsub('CHANNELS', server).empty?
52
+ end
49
53
  end
50
54
  end
51
55
 
@@ -6,26 +6,6 @@ module Plezi
6
6
 
7
7
  module_function
8
8
 
9
- # The maximum number of threads that are used for concurrency.
10
- def max_threads
11
- @max_threads ||= 30
12
- end
13
- # Sets the maximum number of threads that are used for concurrency.
14
- def max_threads=val
15
- @max_threads = val
16
- end
17
-
18
- # The number of second between pings automatically sent by an open websocket.
19
- def autoping
20
- @autoping ||= 45
21
- end
22
- # Sets the number of second between pings automatically sent by an open websocket.
23
- #
24
- # Set to nil or false to disable auto-pinging.
25
- def autoping=val
26
- @autoping = 45
27
- end
28
-
29
9
  # Sets the Redis Channel Name.
30
10
  def redis_channel_name=val
31
11
  return false unless defined? Redis
@@ -35,7 +15,7 @@ module Plezi
35
15
  # Returns the Redis Channel Name used by this app.
36
16
  # @return [String]
37
17
  def redis_channel_name
38
- @redis_channel_name ||= 'Plezi_Redis_Channel'
18
+ @redis_channel_name ||= "#{File.basename($0, '.*')}_Redis_Channel"
39
19
  end
40
20
 
41
21
  # Sets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
@@ -45,11 +25,11 @@ module Plezi
45
25
  #
46
26
  # If the sessage size limit is exceeded, the disconnection will be immidiate as an attack will be assumed. The protocol's normal disconnect sequesnce will be discarded.
47
27
  def ws_message_size_limit=val
48
- GRHttp.ws_message_size_limit = val
28
+ Iodine::Http::Websockets.message_size_limit = val
49
29
  end
50
30
  # Gets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
51
31
  def ws_message_size_limit
52
- GRHttp.ws_message_size_limit
32
+ Iodine::Http::Websockets.message_size_limit
53
33
  end
54
34
 
55
35
  # This Server's UUID, for Redis and unicasting identification.
@@ -58,4 +38,4 @@ module Plezi
58
38
  end
59
39
  end
60
40
  end
61
-
41
+ Iodine.threads = 30
@@ -16,7 +16,7 @@ module Plezi
16
16
  @request = request
17
17
  @params = request.params
18
18
  @flash = response.flash
19
- @host_params = request.io[:params]
19
+ @host_params = request[:host_settings]
20
20
  @response = response
21
21
  @cookies = request.cookies
22
22
  # # \@response["content-type"] ||= ::Plezi.default_content_type
@@ -38,31 +38,24 @@ module Plezi
38
38
  # finish if the response was sent
39
39
  return false if response.headers_sent?
40
40
  # make sure that the session object is available for websocket connections
41
- response.session
41
+ session
42
42
  # complete handshake
43
43
  return self
44
44
  end
45
45
  # handles websocket opening.
46
- def on_open ws
47
- # set broadcasts and return true
48
- @response = ws
49
- ws.autoping Plezi::Settings.autoping if Plezi::Settings.autoping
50
- # create the redis connection (in case this in the first instance of this class)
51
- Plezi.redis
46
+ def on_open
52
47
  super() if defined?(super)
53
48
  end
54
49
  # handles websocket messages.
55
- def on_message ws
56
- super(ws.data) if defined?(super)
50
+ def on_message data
51
+ super if defined?(super)
57
52
  end
58
53
  # handles websocket being closed.
59
- def on_close ws
60
- super() if defined? super
54
+ def on_close
55
+ super if defined? super
61
56
  end
62
57
 
63
58
  # Inner Routing
64
- #
65
- #
66
59
  def _route_path_to_methods_and_set_the_response_
67
60
  #run :before filter
68
61
  return false if self.class.has_method?(:before) && self.before == false
@@ -42,7 +42,7 @@ module Plezi
42
42
 
43
43
  # Session data can be stored here (session data will be stored on the Redis server, if Redis is available).
44
44
  #
45
- # The first time this method is called, the session object will be created. The session object must be created BEFORE the headers are set , if it is to be used.
45
+ # The first time this method is called, the `n object will be created. The session object must be created BEFORE the headers are set , if it is to be used.
46
46
  #
47
47
  # Sessions are not automatically created, because they require more resources. The one exception is the Websocket connection that will force a session object into existence, as it's very common to use session data in Websocket connections and the extra connection time is less relevant for a long term connection.
48
48
  def session
@@ -56,7 +56,7 @@ module Plezi
56
56
  # these cookies will live for one successful request to a Controller and will then be removed.
57
57
  attr_reader :flash
58
58
 
59
- # the parameters used to create the host (the parameters passed to the `listen` / `add_service` call).
59
+ # the parameters used to create the host (the parameters passed to the `Plezi.host`).
60
60
  attr_reader :host_params
61
61
 
62
62
  # this method does two things.
@@ -79,7 +79,6 @@ module Plezi
79
79
  #
80
80
  def redirect_to url, options = {}
81
81
  return super *[] if defined? super
82
- raise 'Cannot redirect once a Websocket connection was established.' if response.is_a?(::GRHttp::WSEvent)
83
82
  raise 'Cannot redirect after headers were sent.' if response.headers_sent?
84
83
  url = "#{request.base_url}/#{url.to_s.gsub('_', '/')}" if url.is_a?(Symbol) || ( url.is_a?(String) && url.empty? ) || url.nil?
85
84
  # redirect
@@ -129,8 +128,6 @@ module Plezi
129
128
  # filename:: sets a filename for the browser to "save as". defaults to empty.
130
129
  #
131
130
  def send_data data, options = {}
132
- raise 'Cannot use "send_data" once a Websocket connection was established.' if response.is_a?(::GRHttp::WSEvent)
133
- # return response.write(data) if response.is_a?(::GRHttp::WSEvent)
134
131
  raise 'Cannot use "send_data" after headers were sent' if response.headers_sent?
135
132
  Plezi.warn 'HTTP response buffer is cleared by `#send_data`' if response.body && response.body.any? && response.body.clear
136
133
  response << data
@@ -180,7 +177,12 @@ module Plezi
180
177
  options[:type] ||= 'html'.freeze
181
178
  options[:locale] ||= params[:locale].to_sym if params[:locale]
182
179
  #update content-type header
183
- response['content-type'] ||= "#{MimeTypeHelper::MIME_DICTIONARY[".#{options[:type]}".freeze]}; charset=utf-8".freeze
180
+ case options[:type]
181
+ when 'html', 'js', 'txt'
182
+ response['content-type'] ||= "#{MimeTypeHelper::MIME_DICTIONARY[".#{options[:type]}".freeze]}; charset=utf-8".freeze
183
+ else
184
+ response['content-type'] ||= "#{MimeTypeHelper::MIME_DICTIONARY[".#{options[:type]}".freeze]}".freeze
185
+ end
184
186
  # Circumvents I18n persistance issues (live updating and thread data storage).
185
187
  I18n.locale = options[:locale] || I18n.default_locale if defined?(I18n) # sets the locale to nil for default behavior even if the locale was set by a previous action - removed: # && options[:locale]
186
188
  # find template and create template object
@@ -201,19 +203,19 @@ module Plezi
201
203
  # respond to websocket special case
202
204
  return :pre_connect if request.upgrade?
203
205
  # respond to save 'new' special case
204
- return (self.class.has_method?(:save) ? :save : false) if request.request_method.match(/POST|PUT|PATCH/) && (params[:id].nil? || params[:id] == 'new')
206
+ return (self.class.has_method?(:save) ? :save : false) if (request.request_method =~ /POST|PUT|PATCH/i.freeze) && (params[:id].nil? || params[:id] == 'new')
205
207
  # set DELETE method if simulated
206
208
  request.request_method = 'DELETE' if params[:_method].to_s.downcase == 'delete'
207
209
  # respond to special :id routing
208
210
  return params[:id].to_s.to_sym if params[:id] && self.class.has_exposed_method?(params[:id].to_s.to_sym)
209
211
  #review general cases
210
212
  case request.request_method
211
- when 'GET', 'HEAD'
213
+ when 'GET'.freeze, 'HEAD'.freeze
212
214
  return (self.class.has_method?(:index) ? :index : false) unless params[:id]
213
215
  return (self.class.has_method?(:show) ? :show : false)
214
- when 'POST', 'PUT', 'PATCH'
216
+ when 'POST'.freeze, 'PUT'.freeze, 'PATCH'.freeze
215
217
  return (self.class.has_method?(:update) ? :update : false)
216
- when 'DELETE'
218
+ when 'DELETE'.freeze
217
219
  return (self.class.has_method?(:delete) ? :delete : false)
218
220
  end
219
221
  false
@@ -4,7 +4,7 @@ module Plezi
4
4
 
5
5
  #####
6
6
  # handles the HTTP Routing
7
- class HTTPRouter
7
+ module HTTPRouter
8
8
 
9
9
  class Host
10
10
  attr_reader :params
@@ -12,8 +12,9 @@ module Plezi
12
12
  def initialize params
13
13
  @params = params
14
14
  @routes = []
15
- params[:assets_public_regex] = /^#{params[:assets_public].to_s.chomp('/')}\/(.+)/.freeze
16
- params[:assets_refuse_templates] = /(#{AssetManager.all_extentions.join('|')}|\.\.\/)$/.freeze
15
+ @params[:assets_public_regex] = /^#{params[:assets_public].to_s.chomp('/')}\//i.freeze
16
+ @params[:assets_public_length] = @params[:assets_public].to_s.chomp('/').length + 1
17
+ @params[:assets_refuse_templates] = /(#{AssetManager.all_extentions.join('|')}|\.\.\/)$/i.freeze
17
18
  end
18
19
  end
19
20
 
@@ -25,23 +26,25 @@ module Plezi
25
26
  def on_upgrade request, response
26
27
  host = get_host(request[:host_name].to_s.downcase) || @hosts[:default]
27
28
  return false unless host
28
- request.io[:params] = host.params
29
+ request[:host_settings] = host.params
29
30
  # return if a route answered the request
30
31
  host.routes.each {|r| a = r.on_request(request, response); return a if a}
31
32
  # websockets should cut out here
32
33
  false
33
34
  end
34
- # initializes an HTTP router (the normal Handler for HTTP requests)
35
+ # initializes the HTTP router (the normal Handler for HTTP requests)
35
36
  #
36
37
  # the router holds the different hosts and sends them messages/requests.
37
- def initialize
38
- @hosts = {}
39
- @active_host = nil
40
- end
38
+ @hosts = {}
39
+ @active_host = nil
41
40
 
42
- # adds a host to the router (or activates an existing host to add new routes). accepts a host name and any parameters not related to the actual connection (ssl etc') (see {Plezi.listen})
41
+ # adds a host to the router (or activates an existing host to add new routes). accepts a host name and any parameters not related to the actual connection (ssl etc') (see {Plezi.host})
43
42
  def add_host host_name, params = {}
44
- host_name = (host_name ? (host_name.is_a?(String) ? host_name.to_s.downcase : host_name) : :default)
43
+ params[:index_file] ||= 'index.html'
44
+ params[:assets_public] ||= '/assets'
45
+ params[:assets_public].chomp! '/'
46
+ params[:public] ||= params[:root] # backwards compatability
47
+ host_name = (host_name.is_a?(String) ? host_name.to_s.downcase : (host_name.is_a?(Regexp) ? host_name : :default))
45
48
  @active_host = get_host(host_name) || ( @hosts[host_name] = Host.new(params) )
46
49
  add_alias host_name, *params[:alias] if params[:alias]
47
50
  @active_host
@@ -49,21 +52,21 @@ module Plezi
49
52
  # adds an alias to an existing host name (normally through the :alias parameter in the `add_host` method).
50
53
  def add_alias host_name, *aliases
51
54
  host = get_host host_name
52
- return false unless host
55
+ host ||= add_host :default
53
56
  aliases.each {|a| @hosts[a.to_s.downcase] = host}
54
57
  true
55
58
  end
56
59
 
57
60
  # adds a route to the active host. The active host is the last host referenced by the `add_host`.
58
61
  def add_route path, controller, &block
59
- raise 'No Host defined.' unless @active_host
60
- @active_host.routes << Route.new(path, controller, &block)
62
+ @active_host ||= add_host :default
63
+ @active_host.routes << ::Plezi::Base::Route.new(path, controller, &block)
61
64
  end
62
65
 
63
66
  # adds a route to all existing hosts.
64
67
  def add_shared_route path, controller, &block
65
- raise 'No Host defined.' if @hosts.empty?
66
- @hosts.each {|n, h| h.routes << Route.new(path, controller, &block) }
68
+ add_host :default if @hosts.empty?
69
+ @hosts.each {|n, h| h.routes << ::Plezi::Base::Route.new(path, controller, &block) }
67
70
  end
68
71
 
69
72
  # handles requests send by the HTTP Protocol (HTTPRequest objects)
@@ -71,7 +74,7 @@ module Plezi
71
74
  begin
72
75
  host = get_host(request[:host_name].to_s.downcase) || @hosts[:default]
73
76
  return false unless host
74
- request.io[:params] = host.params
77
+ request[:host_settings] = host.params
75
78
  # render any assets?
76
79
  return true if render_assets request, response, host.params
77
80
  # send static file, if exists and root is set.
@@ -79,10 +82,10 @@ module Plezi
79
82
  # return if a route answered the request
80
83
  host.routes.each {|r| a = r.on_request(request, response); return a if a}
81
84
  #return error code or 404 not found
82
- return Base::HTTPSender.send_by_code request, response, 404 unless request[:io].params[:http_handler] == ::GRHttp::Base::Rack
85
+ return Base::HTTPSender.send_by_code request, response, 404 unless ( @avoid_404 ||= ( Iodine::Http.on_http == ::Iodine::Http::Rack ? 1 : 0 ) ) == 1
83
86
  rescue => e
84
87
  # return 500 internal server error.
85
- GReactor.error e
88
+ Iodine.error e
86
89
  Base::HTTPSender.send_by_code request, response, 500
87
90
  end
88
91
  end
@@ -105,14 +108,14 @@ module Plezi
105
108
  return true if params[:assets_callback] && params[:assets_callback].call(request, response)
106
109
 
107
110
  # get file requested
108
- source_file = File.join(params[:assets], *(request.path.match(params[:assets_public_regex])[1].split('/')))
111
+ source_file = File.join(params[:assets], *(request.path[params[:assets_public_length]..-1].split('/')))
109
112
 
110
113
 
111
114
  # stop if file name is reserved / has security issues
112
115
  return false if File.directory?(source_file) || source_file =~ params[:assets_refuse_templates]
113
116
 
114
117
  # set where to store the rendered asset
115
- target_file = File.join( params[:public].to_s, params[:assets_public].to_s, *request.path.match(params[:assets_public_regex])[1].split('/') )
118
+ target_file = File.join( params[:public].to_s, *request.path.split('/') )
116
119
 
117
120
  # send the file if it exists (no render needed)
118
121
  if File.exists?(source_file)
@@ -134,7 +137,9 @@ module Plezi
134
137
  # return false if an asset couldn't be rendered and wasn't found.
135
138
  return false
136
139
  end
137
-
140
+ extend self
138
141
  end
142
+ Iodine::Http.on_http ::Plezi::Base::HTTPRouter
143
+ Iodine::Http.on_websocket ::Plezi::Base::HTTPRouter.upgrade_proc
139
144
  end
140
145
  end
@@ -3,15 +3,27 @@ module Plezi
3
3
  # This API wil allows you to listen to Websocket Broadcasts sent to any object and to accept unicasts
4
4
  # even when NOT connected to a websocket.
5
5
  #
6
- # Simpley create a class to handle any events and call `Plezi::Placebo.new ClassName` :
6
+ # Simpley create a class to handle any events and call `Plezi::Placebo.new ClassName` or use the {Plezi.start_placebo} shortcut:
7
7
  #
8
- # class MyListener
9
- # def _my_method_name *args
10
- # #logic
11
- # end
12
- # end
8
+ # # Important: set up a unique - but shared - main redis channel for BOTH Apps (The Plezi and the Placebo).
9
+ # Plezi::Settings.redis_channel_name = 'unique_channel_name_for_app_b24270e2'
10
+ # # Important: set Plezi's auo-Redis pub/sub server.
11
+ # ENV['PL_REDIS_URL'] ||= "redis://redis:password@redis.server.com:9999"
13
12
  #
14
- # Plezi::Placebo.new MyListener
13
+ # # create the Placebo bridge handler
14
+ # class PleziBridge
15
+ # def on_open
16
+ # multicast :print, "Hello from Placebo!"
17
+ # end
18
+ # def print data
19
+ # Iodine.info "Placebo message: #{data}"
20
+ # puts "Placebo message: #{data}"
21
+ # end
22
+ # end
23
+ #
24
+ # # initiate Placebo mode using the bridge class. it's possible to create multiple
25
+ # # it's possible to create multiple bridge classes this way.
26
+ # Plezi.start_placebo(PleziBridge)
15
27
  #
16
28
  # A new instance will be created and that instance will answer any broadcasts, for ALL possible
17
29
  # Plezi controllers, as long as it had a method defined that is capable to handle the broadcast.
@@ -37,15 +49,17 @@ module Plezi
37
49
  module InstanceMethods
38
50
  public
39
51
  attr_accessor :io
40
- def initialize io
41
- @io = io
42
- @io[:websocket_handler] = self
52
+ def initialize io_in, io_out, request
53
+ @io_in = io_in
54
+ @io_out = io_out
55
+ @request = request
43
56
  super()
44
57
  end
45
- # notice of disconnect
58
+ # Cleanup on disconnection
46
59
  def on_close
60
+ io_out.close unless io_out.closed?
47
61
  return super() if defined? super
48
- GR.warn "Placebo #{self.class.superclass.name} disconnected. Ignore if this message appears during shutdown."
62
+ Iodine.warn "Placebo #{self.class.superclass.name} disconnected. Ignore if this message appears during shutdown."
49
63
  end
50
64
  def placebo?
51
65
  true
@@ -60,17 +74,19 @@ module Plezi
60
74
  end
61
75
  end
62
76
  end
63
- class PlaceboIO < GReactor::BasicIO
64
- def clear?
65
- io.closed?
77
+ class PlaceboIO < ::Iodine::Http::Websockets
78
+ # emulate Iodine::Protocol#timeout?
79
+ def timeout? time
80
+ false
66
81
  end
82
+ # emulate Iodine::Protocol#call
67
83
  def call
68
- self.read
69
- GR.warn "Placebo IO recieved IO signal - this is unexpected..."
84
+ read
85
+ Iodine.warn "Placebo IO recieved IO signal - this is unexpected..."
70
86
  end
71
- def on_close
72
- @params[:out].close rescue nil
73
- @cache[:websocket_handler].on_close if @cache[:websocket_handler]
87
+ # override "go_away"
88
+ def go_away
89
+ close
74
90
  end
75
91
  end
76
92
  end
@@ -86,19 +102,10 @@ module Plezi
86
102
  Object.const_set(new_class_name, new_class)
87
103
  end
88
104
  i, o = IO.pipe
89
- io = Placebo::Base::PlaceboIO.new i, out: o, reactor: ::GReactor
90
- new_class.new(io)
105
+ req = {}
106
+ handler = new_class.new(i, o, req)
107
+ io = Placebo::Base::PlaceboIO.new i, handler, req
108
+ handler
91
109
  end
92
110
  end
93
111
  end
94
-
95
-
96
- # class A
97
- # def _hi
98
- # 'hi'
99
- # end
100
- # end
101
- # Plezi::Placebo.new A
102
- # a = nil
103
- # GReactor.each {|h| a= h}
104
- # a[:websocket_handler].on_broadcast GRHttp::WSEvent.new(nil, type: true, data: [], method: :_hi)