shove 1.0.7 → 1.0.8
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.
- data/Gemfile +1 -2
- data/README.markdown +57 -91
- data/Rakefile +0 -23
- data/lib/shove.rb +3 -70
- data/lib/shove/app.rb +40 -33
- data/lib/shove/client/channel.rb +4 -0
- data/lib/shove/client/connection.rb +32 -14
- data/lib/shove/http/request.rb +2 -2
- data/lib/shove/protocol.rb +3 -1
- data/shove.gemspec +1 -3
- data/spec/cassettes/should_be_able_to_authorize_with_the_server.yml +10 -6
- data/spec/cassettes/should_deny_a_connection.yml +10 -6
- data/spec/cassettes/should_deny_a_control_to_a_client.yml +10 -6
- data/spec/cassettes/should_deny_a_publishing_to_a_client.yml +10 -6
- data/spec/cassettes/should_deny_a_subscriptions_to_a_client.yml +10 -6
- data/spec/cassettes/should_deny_publishing_on_a_channel_context.yml +10 -6
- data/spec/cassettes/should_deny_subscriptions_on_a_channel_context.yml +10 -6
- data/spec/cassettes/should_get_a_set_of_nodes_for_the_network.yml +11 -7
- data/spec/cassettes/should_grant_a_connection.yml +10 -6
- data/spec/cassettes/should_grant_a_control_to_a_client.yml +11 -7
- data/spec/cassettes/should_grant_a_publishing_to_a_client.yml +10 -6
- data/spec/cassettes/should_grant_a_subscriptions_to_a_client.yml +10 -6
- data/spec/cassettes/should_grant_publishing_on_a_channel_context.yml +10 -6
- data/spec/cassettes/should_grant_subscriptions_on_a_channel_context.yml +10 -6
- data/spec/cassettes/should_publish_on_a_channel_context.yml +10 -6
- data/spec/cassettes/should_publish_to_a_client.yml +10 -6
- data/spec/helper.rb +0 -2
- data/spec/shove_client_spec.rb +39 -30
- data/spec/shove_http_spec.rb +27 -31
- metadata +20 -40
- data/bin/shove +0 -169
- data/lib/shove/app_directory.rb +0 -103
- data/spec/app_directory_spec.rb +0 -66
- data/spec/cassettes/should_authorize_on_a_channel.yml +0 -26
- data/spec/cassettes/should_authorize_oneself.yml +0 -24
- data/spec/cassettes/should_cancel_a_binding.yml +0 -24
- data/spec/cassettes/should_configure_the_default.yml +0 -24
- data/spec/cassettes/should_configure_the_from_the_previous_test.yml +0 -24
- data/spec/cassettes/should_create_a_channel_context.yml +0 -24
- data/spec/cassettes/should_get_a_subscribe_granted_event.yml +0 -24
- data/spec/cassettes/should_publish.yml +0 -24
- data/spec/cassettes/should_receive_an_unsubscribe_event.yml +0 -24
- data/spec/cassettes/should_receive_messages_on_a_channel.yml +0 -24
- data/spec/cassettes/should_send_a_connect_op.yml +0 -24
- data/spec/cassettes/should_send_a_connect_op_with_an_id.yml +0 -24
- data/spec/cassettes/should_spawn_a_client.yml +0 -24
- data/spec/cassettes/should_subscribe_to_a_channel.yml +0 -24
- data/spec/cassettes/should_trigger_a_connect_denied_event.yml +0 -24
- data/spec/cassettes/should_trigger_a_connect_event.yml +0 -24
- data/spec/cassettes/should_trigger_a_disconnect_event.yml +0 -24
- data/spec/cassettes/should_trigger_an_error_event.yml +0 -24
- data/spec/cassettes/should_unsubscribe_from_a_channel.yml +0 -24
- data/spec/cassettes/should_update_the_default_app.yml +0 -24
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
shove
|
2
|
-
|
3
|
-
|
1
|
+
shove
|
2
|
+
=====
|
3
|
+
HTTP and WebSocket clients for shove.io
|
4
4
|
|
5
5
|
<a name="installation"></a>
|
6
6
|
Installation
|
@@ -11,53 +11,42 @@ gem install shove
|
|
11
11
|
```
|
12
12
|
|
13
13
|
<a name="configuration"></a>
|
14
|
-
|
15
|
-
|
14
|
+
Using Shove
|
15
|
+
-----------
|
16
16
|
|
17
|
-
|
18
|
-
shove though the Shove module:
|
17
|
+
To use shove, you must first create a Shove::App object.
|
19
18
|
|
20
19
|
```ruby
|
21
|
-
Shove.
|
22
|
-
app_id "myappid"
|
23
|
-
app_key "myappkey"
|
24
|
-
|
25
|
-
```
|
26
|
-
|
27
|
-
If you want to work with different shove apps in one project, you can
|
28
|
-
create App objects
|
29
|
-
|
30
|
-
```ruby
|
31
|
-
app = Shove::App.new do
|
32
|
-
app_id "myappid"
|
33
|
-
app_key "myappkey"
|
34
|
-
end
|
20
|
+
app = Shove::App.new(
|
21
|
+
app_id: "myappid",
|
22
|
+
app_key: "myappkey"
|
23
|
+
)
|
35
24
|
```
|
36
25
|
|
37
|
-
|
26
|
+
Get your app_id, and app_key at [shove.io][0]
|
38
27
|
|
39
28
|
<a name="http_client"></a>
|
40
29
|
Using the HTTP Client
|
41
30
|
---------------------
|
42
31
|
The HTTP client gives publishing and access control capabilities without
|
43
|
-
a persistent WebSocket connection. The HTTP client
|
32
|
+
a persistent WebSocket connection. The HTTP client cannot act as a subscriber.
|
44
33
|
|
45
|
-
|
34
|
+
Publish to a channel
|
46
35
|
|
47
36
|
```ruby
|
48
|
-
|
37
|
+
app.channel("notifications").publish("Hello World!")
|
49
38
|
```
|
50
39
|
|
51
40
|
Publish Direct
|
52
41
|
|
53
42
|
```ruby
|
54
|
-
|
43
|
+
app.channel("direct:buddy").publish("Hey buddy")
|
55
44
|
```
|
56
45
|
|
57
46
|
Publish and handle the HTTP response
|
58
47
|
|
59
48
|
```ruby
|
60
|
-
|
49
|
+
app.channel("notifications").publish("...") do |response|
|
61
50
|
if reponse.error?
|
62
51
|
puts "#{response.status} - #{response.error}"
|
63
52
|
end
|
@@ -70,25 +59,25 @@ granular security.
|
|
70
59
|
Grant subscription on the notifications channel
|
71
60
|
|
72
61
|
```ruby
|
73
|
-
|
62
|
+
app.channel("notifications").grant_subscribe("dan@shove.io")
|
74
63
|
```
|
75
64
|
|
76
65
|
Grant subscription on all channels to client dan
|
77
66
|
|
78
67
|
```ruby
|
79
|
-
|
68
|
+
app.channel("*").grant_subscribe("dan@shove.io")
|
80
69
|
```
|
81
70
|
|
82
71
|
Grant publishing on chat:client_22733 channel to client dan
|
83
72
|
|
84
73
|
```ruby
|
85
|
-
|
74
|
+
app.channel("chat:client_22733").grant_publish("dan")
|
86
75
|
```
|
87
76
|
|
88
77
|
Deny publishing on chat:client_22733 channel to dan
|
89
78
|
|
90
79
|
```ruby
|
91
|
-
|
80
|
+
app.channel("chat:client_22733").deny_publish("dan")
|
92
81
|
```
|
93
82
|
|
94
83
|
Sometimes it's easier to give out an access key to a specific
|
@@ -98,37 +87,37 @@ channel, which is also an option.
|
|
98
87
|
Channel Keys
|
99
88
|
------------
|
100
89
|
You can generate channel keys which allow clients of
|
101
|
-
your shove network to
|
90
|
+
your shove network to subscribe or publish to specific
|
102
91
|
channels.
|
103
92
|
|
104
93
|
Example: Create a key for the channel groups:788
|
105
94
|
|
106
95
|
```ruby
|
107
|
-
key =
|
96
|
+
key = app.channel_key "group:788"
|
108
97
|
```
|
109
98
|
|
110
|
-
|
99
|
+
Subscribe only
|
111
100
|
|
112
101
|
```ruby
|
113
|
-
key = app.
|
102
|
+
key = app.subscribe_key "group:788"
|
114
103
|
```
|
115
104
|
|
116
105
|
This functionality becomes useful when you want to give
|
117
|
-
you site users access.
|
106
|
+
you site users access. In your view:
|
118
107
|
|
119
|
-
```
|
120
|
-
|
121
|
-
|
122
|
-
var key = "#{@shove.channel_key(@channel)}";
|
108
|
+
```erb
|
109
|
+
var channel = "<%= @channel %>";
|
110
|
+
var key = "<%= @app.channel_key(@channel) %>";
|
123
111
|
```
|
124
112
|
|
125
|
-
Note: Channel keys are based off the app key. So, in order for
|
126
|
-
them to work, you must specify the app key
|
113
|
+
Note: Channel keys are based off the app key (master key). So, in order for
|
114
|
+
them to work, you must specify the app key in your app.
|
127
115
|
|
128
116
|
```ruby
|
129
|
-
|
130
|
-
|
131
|
-
|
117
|
+
app = Shove::App.new(
|
118
|
+
app_id: "myappid",
|
119
|
+
app_key: "myappkey"
|
120
|
+
)
|
132
121
|
```
|
133
122
|
|
134
123
|
<a name="websocket_client"></a>
|
@@ -139,28 +128,15 @@ requires that you are running an EventMachine reactor.
|
|
139
128
|
|
140
129
|
```ruby
|
141
130
|
EM.run do
|
142
|
-
app = Shove::App.new
|
143
|
-
app_id "myapp"
|
144
|
-
|
145
|
-
|
146
|
-
app.connect
|
131
|
+
app = Shove::App.new(
|
132
|
+
app_id "myapp",
|
133
|
+
app_key: "myappkey"
|
134
|
+
)
|
147
135
|
|
148
|
-
|
149
|
-
client = app.connect "unique_id"
|
136
|
+
client = app.connect
|
150
137
|
end
|
151
138
|
```
|
152
139
|
|
153
|
-
### Authorization
|
154
|
-
The client is treated like any other websocket
|
155
|
-
client and must be authorized to publish and subscribe.
|
156
|
-
|
157
|
-
```ruby
|
158
|
-
client.authorize "app_key"
|
159
|
-
|
160
|
-
# self authorize a particular channel
|
161
|
-
client.channel("channel").authorize "channel_key"
|
162
|
-
```
|
163
|
-
|
164
140
|
### Client events
|
165
141
|
|
166
142
|
Connect event:
|
@@ -195,7 +171,7 @@ client.on("connect_denied") do |id|
|
|
195
171
|
end
|
196
172
|
```
|
197
173
|
|
198
|
-
### Publish and Subscribe
|
174
|
+
### Channels & Publish and Subscribe
|
199
175
|
|
200
176
|
Subscribe to a channel or get a subscribed channel
|
201
177
|
|
@@ -265,37 +241,27 @@ channel.publish("hi!")
|
|
265
241
|
channel.publish(obj.to_json)
|
266
242
|
```
|
267
243
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
```bash
|
274
|
-
shove help
|
275
|
-
```
|
276
|
-
|
277
|
-
Publish a message
|
278
|
-
|
279
|
-
```bash
|
280
|
-
shove publish -c channel1 -m "Hello world!"
|
281
|
-
```
|
282
|
-
|
283
|
-
Publish to a specific app
|
284
|
-
|
285
|
-
```bash
|
286
|
-
shove publish -a app_id -c chan1 -m "hi"
|
287
|
-
```
|
244
|
+
<a name="websocket_client"></a>
|
245
|
+
WebSocket Client without App Key
|
246
|
+
--------------------------------
|
247
|
+
If you are connecting to someone elses app
|
248
|
+
and have limited scope and access, you can get by.
|
288
249
|
|
289
|
-
|
250
|
+
```ruby
|
251
|
+
EM.run do
|
252
|
+
app = Shove::App.new(
|
253
|
+
app_id "myapp"
|
254
|
+
)
|
290
255
|
|
291
|
-
|
292
|
-
shove apps:default -a app_id
|
293
|
-
```
|
256
|
+
client = app.connect "connect-key"
|
294
257
|
|
295
|
-
|
258
|
+
channel = client.channel("channel")
|
259
|
+
channel.auth "channelkey"
|
296
260
|
|
297
|
-
|
298
|
-
|
261
|
+
channel.on("message") do |message|
|
262
|
+
puts message
|
263
|
+
end
|
264
|
+
end
|
299
265
|
```
|
300
266
|
|
301
267
|
[0]: https://shove.io
|
data/Rakefile
CHANGED
@@ -28,26 +28,3 @@ task :autospec => :spec do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
end
|
31
|
-
|
32
|
-
desc "Generate the README HTML"
|
33
|
-
task :readme do
|
34
|
-
|
35
|
-
require "redcarpet"
|
36
|
-
require "albino"
|
37
|
-
|
38
|
-
# Create a custom renderer that uses albino to
|
39
|
-
# make pretty code
|
40
|
-
class Colorizer < Redcarpet::Render::HTML
|
41
|
-
def block_code(code, language)
|
42
|
-
Albino.colorize(code, language)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
content = Redcarpet::Markdown.new(Colorizer, :fenced_code_blocks => true)
|
47
|
-
.render(File.read("README.markdown"))
|
48
|
-
|
49
|
-
File.open("README.html", "w") do |f|
|
50
|
-
f << content
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
data/lib/shove.rb
CHANGED
@@ -7,7 +7,6 @@ require "em-http-request"
|
|
7
7
|
require "em-ws-client"
|
8
8
|
require "yajl"
|
9
9
|
require "yaml"
|
10
|
-
require "confstruct"
|
11
10
|
require "digest/sha1"
|
12
11
|
|
13
12
|
##
|
@@ -18,80 +17,14 @@ require "digest/sha1"
|
|
18
17
|
# See https://github.com/shove/shove for js client documentation
|
19
18
|
module Shove
|
20
19
|
|
21
|
-
Version = "1.0.
|
22
|
-
|
23
|
-
class ShoveException < Exception; end
|
24
|
-
|
25
|
-
class << self
|
26
|
-
|
27
|
-
attr_accessor :config, :app
|
28
|
-
|
29
|
-
# configure shover
|
30
|
-
# +settings+ the settings for the created client as
|
31
|
-
# a string for a yaml file, or as a hash
|
32
|
-
def configure params=nil, &block
|
33
|
-
|
34
|
-
unless defined? @config
|
35
|
-
@config = Confstruct::Configuration.new do
|
36
|
-
api_url "https://api.shove.io"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
if params
|
41
|
-
@config.configure params
|
42
|
-
end
|
20
|
+
Version = "1.0.8"
|
43
21
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
unless defined? @app
|
49
|
-
@app = App.new(@config)
|
50
|
-
else
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# fetch a channel by name
|
56
|
-
# +name+ the name of the channel
|
57
|
-
def channel name
|
58
|
-
@app.channel(name)
|
59
|
-
end
|
60
|
-
|
61
|
-
# fetch a client by id
|
62
|
-
def client id
|
63
|
-
@app.client(id)
|
64
|
-
end
|
65
|
-
|
66
|
-
# validate network settings
|
67
|
-
# used for the CLI
|
68
|
-
def valid?
|
69
|
-
@app.valid?
|
70
|
-
end
|
71
|
-
|
72
|
-
# fetch the available stream nodes
|
73
|
-
# for this network.
|
74
|
-
def hosts
|
75
|
-
@app.hosts
|
76
|
-
end
|
77
|
-
|
78
|
-
# Connect to the default app with a
|
79
|
-
# WebSocket connection
|
80
|
-
def connect
|
81
|
-
@app.connect
|
82
|
-
end
|
83
|
-
|
84
|
-
# Create a channel key
|
85
|
-
# +channel+ the name of the channel
|
86
|
-
def channel_key channel
|
87
|
-
@app.channel_key channel
|
88
|
-
end
|
22
|
+
# Exception class for all shove exception
|
23
|
+
class ShoveException < Exception; end
|
89
24
|
|
90
|
-
end
|
91
25
|
end
|
92
26
|
|
93
27
|
require "shove/app"
|
94
|
-
require "shove/app_directory"
|
95
28
|
require "shove/protocol"
|
96
29
|
require "shove/client/connection"
|
97
30
|
require "shove/client/channel"
|
data/lib/shove/app.rb
CHANGED
@@ -1,38 +1,24 @@
|
|
1
1
|
module Shove
|
2
2
|
class App
|
3
3
|
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :app_key, :app_id, :api_url, :ws_url
|
5
5
|
|
6
6
|
# create an API client
|
7
7
|
# +config+ optional Confstruct
|
8
8
|
# +&block+ config block
|
9
9
|
# Example:
|
10
|
-
# Shove::App.new
|
11
|
-
# app_id "myappid"
|
12
|
-
# app_key "myappkey"
|
13
|
-
#
|
14
|
-
def initialize config=
|
15
|
-
@config
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@config.configure do
|
22
|
-
api_url Shove.config.api_url || "https://api.shove.io"
|
23
|
-
end
|
10
|
+
# Shove::App.new(
|
11
|
+
# app_id: "myappid"
|
12
|
+
# app_key: "myappkey"
|
13
|
+
# )
|
14
|
+
def initialize config={}
|
15
|
+
@config = config
|
16
|
+
@app_id = config[:app_id]
|
17
|
+
@app_key = config[:app_key]
|
18
|
+
@api_url = config[:api_url] || "https://api.shove.io"
|
19
|
+
@ws_url = config[:ws_url]
|
24
20
|
|
25
|
-
|
26
|
-
@config.configure params
|
27
|
-
end
|
28
|
-
|
29
|
-
if block
|
30
|
-
@config.configure(&block)
|
31
|
-
end
|
32
|
-
|
33
|
-
unless @config.app_id
|
34
|
-
raise ShoveException.new("App ID required")
|
35
|
-
end
|
21
|
+
raise ShoveException.new("App ID required") unless @app_id
|
36
22
|
end
|
37
23
|
|
38
24
|
# is the app valid?
|
@@ -43,7 +29,7 @@ module Shove
|
|
43
29
|
|
44
30
|
# get a list of websocket hosts
|
45
31
|
def hosts
|
46
|
-
request("hosts").exec_sync(:get).parse
|
32
|
+
@hosts ||= request("hosts").exec_sync(:get).parse
|
47
33
|
end
|
48
34
|
|
49
35
|
# create a channel context for acting on a channel
|
@@ -60,29 +46,50 @@ module Shove
|
|
60
46
|
|
61
47
|
# the base URL based on the settings
|
62
48
|
def url
|
63
|
-
"#{@
|
49
|
+
"#{@api_url}/apps/#{@app_id}"
|
64
50
|
end
|
65
51
|
|
66
52
|
# Create a default request object with the base URL
|
67
53
|
# +path+ extra path info
|
68
54
|
def request path
|
69
|
-
Http::Request.new("#{url}/#{path}",
|
55
|
+
Http::Request.new("#{url}/#{path}", self)
|
70
56
|
end
|
71
57
|
|
72
58
|
# Generate a channel key for a client to self authorize
|
73
59
|
# publish and subscribe actions.
|
74
60
|
# +channel+ the name of the channel
|
75
61
|
def channel_key channel
|
76
|
-
Digest::SHA1.hexdigest "#{@
|
62
|
+
Digest::SHA1.hexdigest "#{@app_key}-#{channel}!"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generate a channel key for a client to self authorize
|
66
|
+
# publish and subscribe actions.
|
67
|
+
# +channel+ the name of the channel
|
68
|
+
def publish_key channel
|
69
|
+
channel_key channel
|
70
|
+
end
|
71
|
+
|
72
|
+
# Generate a channel key for a client to self authorize
|
73
|
+
# subscribe actions.
|
74
|
+
# +channel+ the name of the channel
|
75
|
+
def subscribe_key channel
|
76
|
+
Digest::SHA1.hexdigest "#{@app_key}-#{channel}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Generate a connect key for a client to self authorize
|
80
|
+
# publish and subscribe actions.
|
81
|
+
# +channel+ the name of the channel
|
82
|
+
def connect_key
|
83
|
+
Digest::SHA1.hexdigest "#{@app_key}-connect"
|
77
84
|
end
|
78
85
|
|
79
86
|
####
|
80
87
|
|
81
88
|
# Connect to shove as a client in the current process
|
82
89
|
# +id+ optional shove id to supply
|
83
|
-
def connect
|
84
|
-
client = Client::Connection.new(self
|
85
|
-
client.connect
|
90
|
+
def connect connect_key=nil
|
91
|
+
client = Client::Connection.new(self)
|
92
|
+
client.connect connect_key
|
86
93
|
client
|
87
94
|
end
|
88
95
|
|