socker 0.0.2 → 0.0.3

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.
@@ -23,6 +23,7 @@ module Socker
23
23
  WEBSOCKET_STANDARD_EVENTS.each(&register_handler(c, env))
24
24
  end
25
25
  end
26
+ # This is needed for Puma so we can log the requests to WebSockets
26
27
  @application.class.instance_eval {
27
28
  define_method(:log) { |message| Socker::App.log(message) }
28
29
  }
@@ -30,34 +31,56 @@ module Socker
30
31
  @application
31
32
  end
32
33
 
33
- def connection(env, opts={}, &block)
34
- conn = Faye::WebSocket.new(env)
35
- yield conn if block_given?
36
- conn.rack_response
37
- end
38
-
39
- def socket(socket=nil)
40
- @socket = socket
41
- end
42
-
34
+ # Helper method your application can use to register new handlers
35
+ # Supported events handlers are:
36
+ #
37
+ # * open - The connection was succesfully established
38
+ # * close - The connection was closed
39
+ # * error - An error occured on the client side
40
+ # * message - A message was received from the socket
41
+ #
42
+ # Handler could be anything that implements the .call method, like
43
+ # lambda, Proc or Method...
44
+ #
43
45
  def on(event, handler)
44
46
  @events ||= {}
47
+ raise "Unable register handler for unsupported event: #{event}" unless event_supported?(event)
45
48
  @events[event] ||= lambda { |socket, ev| handler.call(socket, ev) }
46
49
  end
47
50
 
51
+ # A method used for mounting the application to Rack:
52
+ #
53
+ # run Rack::URLMap.new('/' => MyServer.new.to_app)
54
+ #
48
55
  def to_app
49
56
  @application
50
57
  end
51
58
 
59
+ # The default logging destination for the application.
60
+ # If you want to use custom logging or logging to a file, you can override
61
+ # this method.
62
+ #
52
63
  def self.log(message, level=:info)
53
64
  @log ||= Logger.new($stdout)
54
65
  @log.send(level, message)
55
66
  end
56
67
 
57
- def log(message); self.class.log(message); end
68
+ def log(message)
69
+ self.class.log(message)
70
+ end
58
71
 
59
72
  private
60
73
 
74
+ def connection(env, opts={}, &block)
75
+ conn = Faye::WebSocket.new(env)
76
+ yield conn if block_given?
77
+ conn.rack_response
78
+ end
79
+
80
+ def event_supported?(event)
81
+ true if WEBSOCKET_STANDARD_EVENTS.include?(event.to_sym)
82
+ end
83
+
61
84
  def is_websocket?(env)
62
85
  Faye::WebSocket.websocket?(env)
63
86
  end
@@ -67,24 +90,24 @@ module Socker
67
90
  end
68
91
 
69
92
  def handle_with(event, opts={})
70
- if events[event]
71
- current_class = self.class
72
- lambda do |ev|
73
- @env = Rack::Request.new(opts[:env])
74
- begin
75
- handle(event, opts[:socket])
76
- events[event].call(opts[:socket], ev)
77
- rescue => error
78
- current_class.log("[#{error.class}] #{error.message}\n#{error.backtrace.join("\n")}", :error)
79
- end
93
+ return method(:handle_missing) if !events[event]
94
+ current_class = self.class
95
+ lambda do |ev|
96
+ @env = Rack::Request.new(opts[:env])
97
+ begin
98
+ handle(event, opts[:socket])
99
+ events[event].call(opts[:socket], ev)
100
+ rescue => error
101
+ current_class.log("[#{error.class}] #{error.message}\n#{error.backtrace.join("\n")}", :error)
80
102
  end
81
- else
82
- method(:handle_undefined)
83
103
  end
84
104
  end
85
105
 
86
- def handle_undefined(event)
87
- self.class.log("WARNING: The '#{event.type}' event is not defined.", :error)
106
+ # When the browser sent an event which has no handler defined, show an error
107
+ # message in the log, but don't crash the application.
108
+ #
109
+ def handle_missing(event)
110
+ self.class.log("WARNING: I dont know how to handle the '#{event.type}' event.", :error)
88
111
  end
89
112
 
90
113
  end
@@ -2,18 +2,28 @@ module Socker
2
2
 
3
3
  module EventHandlers
4
4
 
5
+ # The list of active connections.
6
+ # This list is used for 'broadcasting' messages to all active connections
7
+ #
5
8
  def connections
6
9
  @connections ||= []
7
10
  end
8
11
 
12
+ # When a new connection is opened, we save it into the list
13
+ # of connections (so methods like 'broadcast' works). Also the :when_active
14
+ # callback is executed when this is a first connection.
15
+ #
9
16
  def on_open(connection)
10
17
  @callbacks[:when_active].call if connections.empty? and @callbacks[:when_active]
11
18
  connections << connection
12
19
  end
13
20
 
21
+ # When connection is closed, we remove it from the connections list and
22
+ # execute the :when_idle callback.
23
+ #
14
24
  def on_close(connection)
15
25
  connections.delete(connection)
16
- @callbacks[:when_idle].call if connections.empty? and @callbacks[:when_active]
26
+ @callbacks[:when_idle].call if connections.empty? and @callbacks[:when_idle]
17
27
  end
18
28
 
19
29
  def handle(event, connection)
@@ -2,14 +2,30 @@ module Socker
2
2
 
3
3
  module Helper
4
4
 
5
+ # This function send an broadcast message to all active connections.
6
+ # The message must be String (but you can sent a JSON, etc..)
7
+ #
5
8
  def broadcast(message)
6
- connections.each { |c| c.send(message) }
9
+ connections.each do |c|
10
+ begin
11
+ c.send(message)
12
+ rescue => error
13
+ log("ERROR: Connection #{c} seems invalid, ignoring. (#{error.message})")
14
+ end
15
+ end
7
16
  end
8
17
 
18
+ # If the protocol support PING, you can send this to all clients and when
19
+ # they replied with PONG message, you can handle that with callback.
20
+ #
9
21
  def pbroadcast(message, callback)
10
22
  connections.each { |c| c.ping(message, &callback) }
11
23
  end
12
24
 
25
+ # Provide access to the Rack params used for WebSocket connection, ie:
26
+ #
27
+ # socket = new Socket('ws://' + location.hostname + ':' + '9292' + '/?param1=value')
28
+ #
13
29
  def params
14
30
  @env.params
15
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: socker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: