socker 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: