garufa 0.0.1.beta.2 → 1.0.0.rc.1
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.
- checksums.yaml +4 -4
- data/README.md +79 -30
- data/bin/garufa.pid +1 -0
- data/garufa.gemspec +1 -0
- data/lib/garufa/api/api.rb +1 -0
- data/lib/garufa/api/handler.rb +1 -0
- data/lib/garufa/connection.rb +4 -0
- data/lib/garufa/subscription.rb +94 -0
- data/lib/garufa/subscriptions.rb +1 -90
- data/lib/garufa/version.rb +1 -1
- data/test/connection.rb +1 -1
- data/test/helper.rb +2 -3
- data/test/message.rb +1 -1
- data/test/subscriptions.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f7b4a234feb8611e70d7c76e2ad254c97049ad5
|
4
|
+
data.tar.gz: a790c9505d6e62412d0093c91c7c261ae90622e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ccd62ac3a46148dc0991687abbd5563d0095422b36f4ec071ff13c58ac4d15f67957cc0053c8f068c856c6a839abb48e59786b6adb82bd751365af50417ed62
|
7
|
+
data.tar.gz: d6210ef3d2868ab44275e63123165e6a8e6797c3564cfed0b611cf3564ec30358ce084fdd11c40cbfd8f8c23e1f36f264d1090c2c57e1f8a69069cb73d05e887
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
[](https://travis-ci.org/Juanmcuello/garufa)
|
1
|
+
[](https://travis-ci.org/Juanmcuello/garufa)
|
2
|
+
[](https://codeclimate.com/github/Juanmcuello/garufa)
|
2
3
|
|
3
4
|
Garufa
|
4
5
|
====
|
@@ -12,18 +13,14 @@ welcome.
|
|
12
13
|
Intro
|
13
14
|
-----
|
14
15
|
|
15
|
-
Garufa is a Ruby websocket server which implements the Pusher protocol. It
|
16
|
+
Garufa is a Ruby websocket server which implements the Pusher protocol. It is
|
16
17
|
built on top of [Goliath][goliath], a high performance non-blocking web server,
|
17
18
|
and inspired by [Slanger][slanger], another server compatible with Pusher.
|
18
19
|
|
19
|
-
[pusher]: http://pusher.com
|
20
|
-
[goliath]: https://github.com/postrank-labs/goliath/
|
21
|
-
[slanger]: https://github.com/stevegraham/slanger
|
22
|
-
|
23
20
|
Install
|
24
21
|
-------
|
25
22
|
|
26
|
-
|
23
|
+
Be sure you have a ruby version >= 1.9.2
|
27
24
|
|
28
25
|
``` console
|
29
26
|
$ gem install garufa --pre
|
@@ -31,53 +28,105 @@ $ gem install garufa --pre
|
|
31
28
|
$ garufa --help
|
32
29
|
```
|
33
30
|
|
34
|
-
|
31
|
+
Usage
|
35
32
|
-------
|
36
33
|
|
37
|
-
|
34
|
+
Start garufa server:
|
35
|
+
|
36
|
+
``` console
|
37
|
+
$ garufa -sv --app_key app-key --secret app-secret
|
38
|
+
```
|
39
|
+
|
40
|
+
This will start Garufa, logging to stdout in verbose mode. If you want Garufa
|
41
|
+
to run in background (daemonized) just add `-d` flag.
|
42
|
+
|
43
|
+
Now say you want to send events to your browser. Just create an .html file
|
44
|
+
which requires the *pusher.js* library and binds to some events, then point
|
45
|
+
your browser to that file (for testing purpouse, you can just simple open it
|
46
|
+
with your browser).
|
47
|
+
|
48
|
+
Maybe you would like to open your JavaScript console to see JavaScript debug
|
49
|
+
messages.
|
38
50
|
|
39
51
|
``` html
|
40
52
|
<html>
|
41
53
|
<script src="http://js.pusher.com/2.1/pusher.min.js"></script>
|
42
54
|
<script>
|
43
|
-
Pusher.log = function(message) { console.log(message) }
|
44
|
-
Pusher.host = 'localhost'
|
45
|
-
Pusher.ws_port = 8080
|
55
|
+
Pusher.log = function(message) { console.log(message) };
|
56
|
+
Pusher.host = 'localhost';
|
57
|
+
Pusher.ws_port = 8080;
|
46
58
|
|
47
|
-
var appKey = '
|
48
|
-
var pusher = new Pusher(appKey)
|
49
|
-
var channel = pusher.subscribe('my-channel')
|
59
|
+
var appKey = 'app-key';
|
60
|
+
var pusher = new Pusher(appKey);
|
61
|
+
var channel = pusher.subscribe('my-channel');
|
50
62
|
|
51
|
-
channel.bind('my-event', function(data) { alert(data.message) })
|
63
|
+
channel.bind('my-event', function(data) { alert(data.message) });
|
52
64
|
</script>
|
53
65
|
</html>
|
54
66
|
```
|
55
67
|
|
56
|
-
|
68
|
+
Now trigger *my-event* from Ruby code. Be sure you have already installed
|
69
|
+
the *pusher* gem (*gem install pusher*). Open a Ruby console and paste this
|
70
|
+
code:
|
71
|
+
|
72
|
+
|
57
73
|
``` ruby
|
58
|
-
# server.rb
|
59
74
|
require 'pusher'
|
60
75
|
|
61
76
|
Pusher.host = 'localhost'
|
62
77
|
Pusher.port = 8080
|
63
78
|
|
64
|
-
Pusher.app_id = '
|
65
|
-
Pusher.key = '
|
66
|
-
Pusher.secret = '
|
79
|
+
Pusher.app_id = 'my-app'
|
80
|
+
Pusher.key = 'app-key'
|
81
|
+
Pusher.secret = 'app-secret'
|
67
82
|
|
68
83
|
Pusher.trigger('my-channel', 'my-event', { message: 'hello world' })
|
69
84
|
```
|
70
85
|
|
71
|
-
|
86
|
+
Check your browser to see the event have just arrived.
|
87
|
+
|
88
|
+
SSL support
|
89
|
+
-----------
|
90
|
+
|
91
|
+
``` console
|
92
|
+
$ garufa -sv --app_key app-key --secret app-secret --ssl --ssl-cert /path/to/cert.pem --ssl-key /path/to/key.key
|
93
|
+
```
|
94
|
+
|
95
|
+
**NOTE**: At the moment, Garufa uses the same port for API messages and websocket
|
96
|
+
connections. This means that if you start the server with ssl enabled, you will
|
97
|
+
have to enable ssl in the client library as well as in the api client.
|
98
|
+
|
99
|
+
|
100
|
+
Testing and Contributing
|
101
|
+
------------------------
|
102
|
+
|
103
|
+
It's up to you how you install Garufa dependencies for development and testing,
|
104
|
+
just be sure you have installed dependencies listed in the .gemspec. If you want
|
105
|
+
to let *bundler* handle this, you can generate a Gemfile from the .gemspec and
|
106
|
+
then just run *bundle install*.
|
107
|
+
|
108
|
+
|
109
|
+
``` console
|
110
|
+
$ bundle init --gemspec=garufa.gemspec
|
111
|
+
$ bundle install
|
112
|
+
```
|
113
|
+
|
114
|
+
Once you have dependencies installed, just run *rake test*, or just *rake*, as
|
115
|
+
*test* is the default task.
|
116
|
+
|
117
|
+
``` console
|
118
|
+
$ rake
|
119
|
+
```
|
120
|
+
|
121
|
+
Pull requests are welcome!
|
72
122
|
|
73
|
-
``` console
|
74
|
-
$ garufa -sv --app_key my-application-key --secret my-application-secret
|
75
|
-
```
|
76
123
|
|
77
|
-
|
124
|
+
Pusher
|
125
|
+
------
|
78
126
|
|
79
|
-
|
127
|
+
[Pusher][pusher] is a great service, very well documented and with excellent
|
128
|
+
support. Consider using it on production.
|
80
129
|
|
81
|
-
|
82
|
-
|
83
|
-
|
130
|
+
[pusher]: http://pusher.com
|
131
|
+
[goliath]: https://github.com/postrank-labs/goliath/
|
132
|
+
[slanger]: https://github.com/stevegraham/slanger
|
data/bin/garufa.pid
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
17188
|
data/garufa.gemspec
CHANGED
data/lib/garufa/api/api.rb
CHANGED
data/lib/garufa/api/handler.rb
CHANGED
data/lib/garufa/connection.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'garufa/config'
|
2
|
+
require 'garufa/subscriptions'
|
3
|
+
|
4
|
+
module Garufa
|
5
|
+
class Subscription
|
6
|
+
attr_reader :data, :connection, :error
|
7
|
+
|
8
|
+
def initialize(data, connection)
|
9
|
+
@data, @connection = data, connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def subscribe
|
13
|
+
case true
|
14
|
+
when !valid_channel?
|
15
|
+
set_error(nil, 'Invalid channel')
|
16
|
+
when !public_channel? && !valid_signature?
|
17
|
+
set_error(nil, 'Invalid signature')
|
18
|
+
when !public_channel? && !valid_app_key?
|
19
|
+
set_error(nil, 'Invalid key')
|
20
|
+
when already_subscribed?
|
21
|
+
set_error(nil, "Already subscribed to channel: #{channel}")
|
22
|
+
else
|
23
|
+
Subscriptions.add self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def unsubscribe
|
28
|
+
Subscriptions.remove self
|
29
|
+
end
|
30
|
+
|
31
|
+
def public_channel?
|
32
|
+
!(private_channel? || presence_channel?)
|
33
|
+
end
|
34
|
+
|
35
|
+
def private_channel?
|
36
|
+
channel_prefix == 'private'
|
37
|
+
end
|
38
|
+
|
39
|
+
def presence_channel?
|
40
|
+
channel_prefix == 'presence'
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_error(code, message)
|
44
|
+
@error = SubscriptionError.new(code, message)
|
45
|
+
end
|
46
|
+
|
47
|
+
def success?
|
48
|
+
@error.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def channel
|
52
|
+
@data['channel']
|
53
|
+
end
|
54
|
+
|
55
|
+
def channel_prefix
|
56
|
+
channel[/^private-|presence-/].to_s[0...-1]
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def valid_channel?
|
62
|
+
channel.is_a?(String) && !channel.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_app_key?
|
66
|
+
app_key && app_key == Config[:app_key]
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_signature?
|
70
|
+
string_to_sign = [@connection.socket_id, channel].compact.join(':')
|
71
|
+
token(string_to_sign) == signature
|
72
|
+
end
|
73
|
+
|
74
|
+
def token(string_to_sign)
|
75
|
+
digest = OpenSSL::Digest::SHA256.new
|
76
|
+
OpenSSL::HMAC.hexdigest(digest, Config[:secret], string_to_sign)
|
77
|
+
end
|
78
|
+
|
79
|
+
def already_subscribed?
|
80
|
+
Subscriptions.include? self
|
81
|
+
end
|
82
|
+
|
83
|
+
def app_key
|
84
|
+
@data['auth'].split(':').first if @data['auth']
|
85
|
+
end
|
86
|
+
|
87
|
+
def signature
|
88
|
+
@data['auth'].split(':').last if @data['auth']
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class SubscriptionError < Struct.new(:code, :message)
|
93
|
+
end
|
94
|
+
end
|
data/lib/garufa/subscriptions.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'set'
|
2
|
+
require 'garufa/message'
|
2
3
|
|
3
4
|
module Garufa
|
4
5
|
module Subscriptions
|
@@ -42,94 +43,4 @@ module Garufa
|
|
42
43
|
@subscriptions ||= Hash.new { |h, k| h[k] = Set.new }
|
43
44
|
end
|
44
45
|
end
|
45
|
-
|
46
|
-
class Subscription
|
47
|
-
attr_reader :data, :connection, :error
|
48
|
-
|
49
|
-
def initialize(data, connection)
|
50
|
-
@data, @connection = data, connection
|
51
|
-
end
|
52
|
-
|
53
|
-
def subscribe
|
54
|
-
case true
|
55
|
-
when !valid_channel?
|
56
|
-
set_error(nil, 'Invalid channel')
|
57
|
-
when !public_channel? && !valid_signature?
|
58
|
-
set_error(nil, 'Invalid signature')
|
59
|
-
when !public_channel? && !valid_app_key?
|
60
|
-
set_error(nil, 'Invalid key')
|
61
|
-
when already_subscribed?
|
62
|
-
set_error(nil, "Already subscribed to channel: #{channel}")
|
63
|
-
else
|
64
|
-
Subscriptions.add self
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def unsubscribe
|
69
|
-
Subscriptions.remove self
|
70
|
-
end
|
71
|
-
|
72
|
-
def public_channel?
|
73
|
-
!(private_channel? || presence_channel?)
|
74
|
-
end
|
75
|
-
|
76
|
-
def private_channel?
|
77
|
-
channel_prefix == 'private'
|
78
|
-
end
|
79
|
-
|
80
|
-
def presence_channel?
|
81
|
-
channel_prefix == 'presence'
|
82
|
-
end
|
83
|
-
|
84
|
-
def set_error(code, message)
|
85
|
-
@error = SubscriptionError.new(code, message)
|
86
|
-
end
|
87
|
-
|
88
|
-
def success?
|
89
|
-
@error.nil?
|
90
|
-
end
|
91
|
-
|
92
|
-
def channel
|
93
|
-
@data['channel']
|
94
|
-
end
|
95
|
-
|
96
|
-
def channel_prefix
|
97
|
-
channel[/^private-|presence-/].to_s[0...-1]
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
|
102
|
-
def valid_channel?
|
103
|
-
channel.is_a?(String) && !channel.empty?
|
104
|
-
end
|
105
|
-
|
106
|
-
def valid_app_key?
|
107
|
-
app_key && app_key == Config[:app_key]
|
108
|
-
end
|
109
|
-
|
110
|
-
def valid_signature?
|
111
|
-
string_to_sign = [@connection.socket_id, channel].compact.join(':')
|
112
|
-
token(string_to_sign) == signature
|
113
|
-
end
|
114
|
-
|
115
|
-
def token(string_to_sign)
|
116
|
-
digest = OpenSSL::Digest::SHA256.new
|
117
|
-
OpenSSL::HMAC.hexdigest(digest, Config[:secret], string_to_sign)
|
118
|
-
end
|
119
|
-
|
120
|
-
def already_subscribed?
|
121
|
-
Subscriptions.include? self
|
122
|
-
end
|
123
|
-
|
124
|
-
def app_key
|
125
|
-
@data['auth'].split(':').first if @data['auth']
|
126
|
-
end
|
127
|
-
|
128
|
-
def signature
|
129
|
-
@data['auth'].split(':').last if @data['auth']
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
class SubscriptionError < Struct.new(:code, :message)
|
134
|
-
end
|
135
46
|
end
|
data/lib/garufa/version.rb
CHANGED
data/test/connection.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
$:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
|
2
|
-
|
3
|
-
require "garufa"
|
4
1
|
require 'minitest/autorun'
|
5
2
|
require 'minitest/mock'
|
6
3
|
|
4
|
+
require_relative "../lib/garufa"
|
5
|
+
|
7
6
|
Garufa::Config[:app_key] = '123123-123123'
|
8
7
|
Garufa::Config[:secret] = '456456-456456'
|
9
8
|
|
data/test/message.rb
CHANGED
data/test/subscriptions.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: garufa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 1.0.0.rc.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Manuel Cuello
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: goliath
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- lib/garufa/goliath/connection.rb
|
110
110
|
- lib/garufa/api/api.rb
|
111
111
|
- lib/garufa/api/handler.rb
|
112
|
+
- lib/garufa/subscription.rb
|
112
113
|
- lib/garufa/websocket/websocket.rb
|
113
114
|
- lib/garufa/message.rb
|
114
115
|
- lib/garufa/config.rb
|
@@ -117,6 +118,7 @@ files:
|
|
117
118
|
- lib/garufa/garufa_app.rb
|
118
119
|
- lib/garufa/connection.rb
|
119
120
|
- lib/garufa.rb
|
121
|
+
- bin/garufa.pid
|
120
122
|
- bin/garufa
|
121
123
|
- garufa.gemspec
|
122
124
|
- test/helper.rb
|
@@ -134,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
136
|
requirements:
|
135
137
|
- - '>='
|
136
138
|
- !ruby/object:Gem::Version
|
137
|
-
version: '
|
139
|
+
version: '1.9'
|
138
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
141
|
requirements:
|
140
142
|
- - '>'
|