slanger 0.4.4 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +5 -2
- data/bin/slanger +5 -4
- data/lib/slanger/api/request_validation.rb +2 -2
- data/lib/slanger/channel.rb +14 -0
- data/lib/slanger/connection.rb +1 -1
- data/lib/slanger/handler.rb +2 -2
- data/lib/slanger/presence_channel.rb +1 -1
- data/lib/slanger/redis.rb +1 -1
- data/lib/slanger/version.rb +1 -1
- data/lib/slanger/web_socket_server.rb +4 -2
- data/slanger.rb +4 -4
- data/spec/integration/channel_spec.rb +7 -7
- data/spec/integration/integration_spec.rb +5 -5
- data/spec/integration/presence_channel_spec.rb +14 -15
- data/spec/integration/private_channel_spec.rb +4 -4
- data/spec/integration/replaced_handler_spec.rb +1 -1
- data/spec/integration/ssl_spec.rb +1 -1
- data/spec/unit/channel_spec.rb +36 -0
- data/spec/unit/request_validation_spec.rb +2 -2
- data/spec/unit/webhook_spec.rb +1 -1
- metadata +5 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fce992bf7da1961b629f9c2acad242d07871f7d1f6c9b7ab405f247d53887e9f
|
4
|
+
data.tar.gz: 33cf202ea4f9d4e7ee245eaa4d7b613dc589ce8bfa5975a2427485a0463d726b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a74747925333bba78821f0105464e63f692869e46065ac1c043311acf9375f677b9de75a6dc27d1482cd1a7bdc4dd4fa82f04efd66ad1a65753345ff99790bbd
|
7
|
+
data.tar.gz: baa4433570751fd6eb0e726230fe7040bceb357c79fcf3dba27fa6ec16b80748a2fd5ffcfa88c0534c1dd670ffaa9a33cfb6058283ba7a20ff10f22666a4e030
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Slanger
|
2
2
|
|
3
|
+
## UNMAINTAINED - Slanger is deprecated and unmaintained by its authors. Use at your own risk.
|
4
|
+
|
3
5
|
[![Gem Version](https://badge.fury.io/rb/slanger.svg)](http://badge.fury.io/rb/slanger) [![Build Status](https://travis-ci.org/stevegraham/slanger.svg?branch=master)](https://travis-ci.org/stevegraham/slanger)
|
4
6
|
|
5
7
|
**Important! Slanger is not supposed to be included in your Gemfile. RubyGems is used as a distribution mechanism. If you include it in your app, you will likely get dependency conflicts. PRs updating dependencies for compatibility with your app will be closed. Thank you for reading and enjoy Slanger!**
|
6
8
|
|
7
|
-
##Typical usage
|
9
|
+
## Typical usage
|
8
10
|
|
9
11
|
```
|
10
12
|
gem install slanger
|
@@ -19,7 +21,8 @@ installed as a gem.
|
|
19
21
|
|
20
22
|
Bundler has multiple purposes, one of which is useful for installation.
|
21
23
|
|
22
|
-
##About
|
24
|
+
## About
|
25
|
+
|
23
26
|
Slanger is an open source server implementation of the Pusher protocol written
|
24
27
|
in Ruby. It is designed to scale horizontally across N nodes and to be agnostic
|
25
28
|
as to which Slanger node a subscriber is connected to, i.e subscribers to the
|
data/bin/slanger
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
4
|
require 'optparse'
|
5
|
-
require 'bundler/setup'
|
6
5
|
require 'eventmachine'
|
7
6
|
require 'yaml'
|
8
7
|
require 'active_support/core_ext/hash'
|
@@ -92,15 +91,17 @@ end
|
|
92
91
|
|
93
92
|
if options[:tls_options]
|
94
93
|
[:cert_chain_file, :private_key_file].each do |param|
|
95
|
-
raise RuntimeError.new "--#{param} does not exist at `#{options[:tls_options][param]}`" unless File.exists? options[:tls_options][param]
|
96
94
|
raise RuntimeError.new "Both --cert_file and --private_key_file need to be specified" unless options[:tls_options][param]
|
95
|
+
raise RuntimeError.new "--#{param} does not exist at `#{options[:tls_options][param]}`" unless File.exists? options[:tls_options][param]
|
97
96
|
end
|
98
97
|
end
|
99
98
|
|
100
99
|
STDOUT.sync = true
|
101
100
|
|
102
|
-
|
103
|
-
EM.
|
101
|
+
case
|
102
|
+
when EM.epoll? then EM.epoll
|
103
|
+
when EM.kqueue? then EM.kqueue
|
104
|
+
end
|
104
105
|
|
105
106
|
EM.run do
|
106
107
|
File.tap { |f| require f.expand_path(f.join(f.dirname(__FILE__),'..', 'slanger.rb')) }
|
@@ -12,7 +12,7 @@ module Slanger
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def data
|
15
|
-
@data ||= Oj.
|
15
|
+
@data ||= Oj.strict_load(body["data"] || params["data"])
|
16
16
|
end
|
17
17
|
|
18
18
|
def body
|
@@ -87,7 +87,7 @@ module Slanger
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def assert_valid_json!(string)
|
90
|
-
Oj.
|
90
|
+
Oj.strict_load(string)
|
91
91
|
rescue Oj::ParserError
|
92
92
|
raise Slanger::InvalidRequest.new("Invalid request body: #{raw_body}")
|
93
93
|
end
|
data/lib/slanger/channel.rb
CHANGED
@@ -83,10 +83,24 @@ module Slanger
|
|
83
83
|
# which will send it to subscribed clients.
|
84
84
|
def dispatch(message, channel)
|
85
85
|
push(Oj.dump(message, mode: :compat)) unless channel =~ /\Aslanger:/
|
86
|
+
|
87
|
+
perform_client_webhook!(message)
|
86
88
|
end
|
87
89
|
|
88
90
|
def authenticated?
|
89
91
|
channel_id =~ /\Aprivate-/ || channel_id =~ /\Apresence-/
|
90
92
|
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def perform_client_webhook!(message)
|
97
|
+
if (message['event'].start_with?('client-')) then
|
98
|
+
|
99
|
+
event = message.merge({'name' => 'client_event'})
|
100
|
+
event['data'] = Oj.dump(event['data'])
|
101
|
+
|
102
|
+
Slanger::Webhook.post(event)
|
103
|
+
end
|
104
|
+
end
|
91
105
|
end
|
92
106
|
end
|
data/lib/slanger/connection.rb
CHANGED
data/lib/slanger/handler.rb
CHANGED
@@ -25,9 +25,9 @@ module Slanger
|
|
25
25
|
# Dispatches message handling to method with same name as
|
26
26
|
# the event name
|
27
27
|
def onmessage(msg)
|
28
|
-
msg = Oj.
|
28
|
+
msg = Oj.strict_load(msg)
|
29
29
|
|
30
|
-
msg['data'] = Oj.
|
30
|
+
msg['data'] = Oj.strict_load(msg['data']) if msg['data'].is_a? String
|
31
31
|
|
32
32
|
event = msg['event'].gsub(/\Apusher:/, 'pusher_')
|
33
33
|
|
@@ -32,7 +32,7 @@ module Slanger
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def subscribe(msg, callback, &blk)
|
35
|
-
channel_data = Oj.
|
35
|
+
channel_data = Oj.strict_load msg['data']['channel_data']
|
36
36
|
public_subscription_id = SecureRandom.uuid
|
37
37
|
|
38
38
|
# Send event about the new subscription to the Redis slanger:connection_notification Channel.
|
data/lib/slanger/redis.rb
CHANGED
@@ -25,7 +25,7 @@ module Slanger
|
|
25
25
|
def subscriber
|
26
26
|
@subscriber ||= new_connection.pubsub.tap do |c|
|
27
27
|
c.on(:message) do |channel, message|
|
28
|
-
message = Oj.
|
28
|
+
message = Oj.strict_load(message)
|
29
29
|
c = Channel.from message['channel']
|
30
30
|
c.dispatch message, channel
|
31
31
|
end
|
data/lib/slanger/version.rb
CHANGED
data/slanger.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'bundler/setup'
|
3
|
-
|
4
2
|
require 'eventmachine'
|
5
3
|
require 'em-hiredis'
|
6
4
|
require 'rack'
|
@@ -9,8 +7,10 @@ require File.join(File.dirname(__FILE__), 'lib', 'slanger', 'version')
|
|
9
7
|
|
10
8
|
module Slanger; end
|
11
9
|
|
12
|
-
|
13
|
-
EM.
|
10
|
+
case
|
11
|
+
when EM.epoll? then EM.epoll
|
12
|
+
when EM.kqueue? then EM.kqueue
|
13
|
+
end
|
14
14
|
|
15
15
|
File.tap do |f|
|
16
16
|
Dir[f.expand_path(f.join(f.dirname(__FILE__),'lib', 'slanger', '*.rb'))].each do |file|
|
@@ -18,7 +18,7 @@ describe 'Integration:' do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
messages.
|
21
|
+
expect(messages).to have_attributes connection_established: true, id_present: true,
|
22
22
|
last_event: 'an_event', last_data: { some: "Mit Raben Und Wölfen" }.to_json
|
23
23
|
end
|
24
24
|
|
@@ -36,7 +36,7 @@ describe 'Integration:' do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
messages.
|
39
|
+
expect(messages).to have_attributes connection_established: true, id_present: true,
|
40
40
|
last_event: 'not_excluded_socket_event', last_data: { some: "Mit Raben Und Wölfen" }.to_json
|
41
41
|
end
|
42
42
|
|
@@ -52,7 +52,7 @@ describe 'Integration:' do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
messages.last.
|
55
|
+
expect(messages.last).to eq({"event"=>"pusher:error", "data"=>"{\"code\":null,\"message\":\"Existing subscription to MY_CHANNEL\"}"})
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'supports unsubscribing to channels without closing the socket' do
|
@@ -77,7 +77,7 @@ describe 'Integration:' do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
messages.
|
80
|
+
expect(messages).to have_attributes connection_established: true, id_present: true,
|
81
81
|
last_event: 'pusher_internal:subscription_succeeded', count: 2
|
82
82
|
end
|
83
83
|
|
@@ -105,10 +105,10 @@ describe 'Integration:' do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
client1_messages.
|
108
|
+
expect(client1_messages).to have_attributes count: 2
|
109
109
|
|
110
|
-
client2_messages.
|
111
|
-
|
110
|
+
expect(client2_messages).to have_attributes last_event: 'an_event',
|
111
|
+
last_data: { some: 'data' }.to_json
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
@@ -10,7 +10,7 @@ describe 'Integration' do
|
|
10
10
|
messages = em_stream(key: 'bogus_key') do |websocket, messages|
|
11
11
|
websocket.callback { EM.stop }
|
12
12
|
end
|
13
|
-
messages.
|
13
|
+
expect(messages).to have_attributes count: 1, last_event: 'pusher:error',
|
14
14
|
connection_established: false, id_present: false
|
15
15
|
messages.first['data'] == 'Could not find app by key bogus_key'
|
16
16
|
end
|
@@ -21,7 +21,7 @@ describe 'Integration' do
|
|
21
21
|
messages = em_stream do |websocket, messages|
|
22
22
|
websocket.callback { EM.stop }
|
23
23
|
end
|
24
|
-
messages.
|
24
|
+
expect(messages).to have_attributes activity_timeout: Slanger::Config.activity_timeout,
|
25
25
|
connection_established: true, id_present: true
|
26
26
|
end
|
27
27
|
end
|
@@ -31,7 +31,7 @@ describe 'Integration' do
|
|
31
31
|
messages = em_stream do |websocket, messages|
|
32
32
|
websocket.callback { EM.stop }
|
33
33
|
end
|
34
|
-
messages.
|
34
|
+
expect(messages).to have_attributes connection_established: true, id_present: true
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -40,7 +40,7 @@ describe 'Integration' do
|
|
40
40
|
messages = em_stream(protocol: "20") do |websocket, messages|
|
41
41
|
websocket.callback { EM.stop }
|
42
42
|
end
|
43
|
-
messages.
|
43
|
+
expect(messages).to have_attributes connection_established: false, id_present: false,
|
44
44
|
last_event: 'pusher:error'
|
45
45
|
end
|
46
46
|
|
@@ -48,7 +48,7 @@ describe 'Integration' do
|
|
48
48
|
messages = em_stream(protocol: nil) do |websocket, messages|
|
49
49
|
websocket.callback { EM.stop }
|
50
50
|
end
|
51
|
-
messages.
|
51
|
+
expect(messages).to have_attributes connection_established: false, id_present: false,
|
52
52
|
last_event: 'pusher:error'
|
53
53
|
end
|
54
54
|
end
|
@@ -19,7 +19,7 @@ describe 'Integration' do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
messages.
|
22
|
+
expect(messages).to have_attributes connection_established: true, id_present: true,
|
23
23
|
count: 2,
|
24
24
|
last_event: 'pusher:error'
|
25
25
|
|
@@ -46,11 +46,11 @@ describe 'Integration' do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
messages.
|
49
|
+
expect(messages).to have_attributes first_event: 'pusher:connection_established', count: 2,
|
50
50
|
id_present: true
|
51
51
|
|
52
52
|
# Channel id should be in the payload
|
53
|
-
messages.last['event'].
|
53
|
+
expect(messages.last['event']).to eq('pusher:error')
|
54
54
|
expect(JSON.parse(messages.last['data'])['message']).to match /^Invalid signature: Expected HMAC SHA256 hex digest of/
|
55
55
|
end
|
56
56
|
end
|
@@ -69,11 +69,11 @@ describe 'Integration' do
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
messages.
|
72
|
+
expect(messages).to have_attributes connection_established: true, count: 2
|
73
73
|
|
74
|
-
messages.last.
|
74
|
+
expect(messages.last).to eq({"channel"=>"presence-channel",
|
75
75
|
"event" =>"pusher_internal:subscription_succeeded",
|
76
|
-
"data" => "{\"presence\":{\"count\":1,\"ids\":[\"0f177369a3b71275d25ab1b44db9f95f\"],\"hash\":{\"0f177369a3b71275d25ab1b44db9f95f\":{\"name\":\"SG\"}}}}"}
|
76
|
+
"data" => "{\"presence\":{\"count\":1,\"ids\":[\"0f177369a3b71275d25ab1b44db9f95f\"],\"hash\":{\"0f177369a3b71275d25ab1b44db9f95f\":{\"name\":\"SG\"}}}}"})
|
77
77
|
end
|
78
78
|
|
79
79
|
|
@@ -87,8 +87,7 @@ describe 'Integration' do
|
|
87
87
|
send_subscribe(user: user1,
|
88
88
|
user_id: '0f177369a3b71275d25ab1b44db9f95f',
|
89
89
|
name: 'SG',
|
90
|
-
message: messages.first
|
91
|
-
)
|
90
|
+
message: messages.first)
|
92
91
|
|
93
92
|
when 2
|
94
93
|
new_websocket.tap do |u|
|
@@ -107,13 +106,13 @@ describe 'Integration' do
|
|
107
106
|
|
108
107
|
end
|
109
108
|
|
110
|
-
messages.
|
109
|
+
expect(messages).to have_attributes connection_established: true, count: 3
|
111
110
|
# Channel id should be in the payload
|
112
|
-
messages[1].
|
113
|
-
|
111
|
+
expect(messages[1]).to eq({"channel"=>"presence-channel", "event"=>"pusher_internal:subscription_succeeded",
|
112
|
+
"data"=>"{\"presence\":{\"count\":1,\"ids\":[\"0f177369a3b71275d25ab1b44db9f95f\"],\"hash\":{\"0f177369a3b71275d25ab1b44db9f95f\":{\"name\":\"SG\"}}}}"})
|
114
113
|
|
115
|
-
messages.last.
|
116
|
-
|
114
|
+
expect(messages.last).to eq({"channel"=>"presence-channel", "event"=>"pusher_internal:member_added",
|
115
|
+
"data"=>{"user_id"=>"37960509766262569d504f02a0ee986d", "user_info"=>{"name"=>"CHROME"}}})
|
117
116
|
end
|
118
117
|
|
119
118
|
it 'does not send multiple member added and member removed messages if one subscriber opens multiple connections, i.e. multiple browser tabs.' do
|
@@ -147,8 +146,8 @@ describe 'Integration' do
|
|
147
146
|
end
|
148
147
|
|
149
148
|
# There should only be one set of presence messages sent to the refernce user for the second user.
|
150
|
-
messages.one? { |message| message['event'] == 'pusher_internal:member_added' && message['data']['user_id'] == '37960509766262569d504f02a0ee986d' }.
|
151
|
-
messages.one? { |message| message['event'] == 'pusher_internal:member_removed' && message['data']['user_id'] == '37960509766262569d504f02a0ee986d' }.
|
149
|
+
expect(messages.one? { |message| message['event'] == 'pusher_internal:member_added' && message['data']['user_id'] == '37960509766262569d504f02a0ee986d' }).to eq(true)
|
150
|
+
expect(messages.one? { |message| message['event'] == 'pusher_internal:member_removed' && message['data']['user_id'] == '37960509766262569d504f02a0ee986d' }).to eq(true)
|
152
151
|
|
153
152
|
end
|
154
153
|
end
|
@@ -17,7 +17,7 @@ describe 'Integration' do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
messages.
|
20
|
+
expect(messages).to have_attributes connection_established: true,
|
21
21
|
count: 2,
|
22
22
|
id_present: true,
|
23
23
|
last_event: 'pusher_internal:subscription_succeeded'
|
@@ -37,7 +37,7 @@ describe 'Integration' do
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
messages.
|
40
|
+
expect(messages).to have_attributes connection_established: true, count: 2, id_present: true, last_event:
|
41
41
|
'pusher:error'
|
42
42
|
|
43
43
|
expect(JSON.parse(messages.last['data'])['message']).to match /^Invalid signature: Expected HMAC SHA256 hex digest of/
|
@@ -71,8 +71,8 @@ describe 'Integration' do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
client1_messages.one?
|
75
|
-
client2_messages.none?
|
74
|
+
expect(client1_messages.one? { |m| m['event'] == 'client-something' }).to eq(true)
|
75
|
+
expect(client2_messages.none? { |m| m['event'] == 'client-something' }).to eq(true)
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -12,7 +12,7 @@ describe 'Integration' do
|
|
12
12
|
expected_cert = OpenSSL::X509::Certificate.new(File.open('spec/server.crt'))
|
13
13
|
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
|
14
14
|
ssl_socket.connect
|
15
|
-
ssl_socket.peer_cert.to_s.
|
15
|
+
expect(ssl_socket.peer_cert.to_s).to eq(expected_cert.to_s)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/spec/unit/channel_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'slanger'
|
3
|
+
require 'oj'
|
3
4
|
|
4
5
|
def clear_redis_connections
|
5
6
|
Slanger::Redis.instance_variables.each do |ivar|
|
@@ -66,4 +67,39 @@ describe 'Slanger::Channel' do
|
|
66
67
|
3.times { channel.subscribe { |m| nil } }
|
67
68
|
end
|
68
69
|
end
|
70
|
+
|
71
|
+
describe '#dispatch' do
|
72
|
+
it 'activates a webhook when client events are received' do
|
73
|
+
message = {
|
74
|
+
'event' => 'client-test_event',
|
75
|
+
'channel' => 'private-test_channel',
|
76
|
+
'socket_id' => '8.422225',
|
77
|
+
'data' => { 'key' => 'value' }
|
78
|
+
}
|
79
|
+
|
80
|
+
expected_params = message.merge({
|
81
|
+
'name' => 'client_event',
|
82
|
+
'data' => Oj.dump(message['data'])
|
83
|
+
})
|
84
|
+
|
85
|
+
Slanger::Webhook.expects(:post).
|
86
|
+
with(expected_params).
|
87
|
+
once
|
88
|
+
|
89
|
+
channel.dispatch(message, 'private-test_channel')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'does not activate a webhook when non-client event messages are received' do
|
93
|
+
message = {
|
94
|
+
'event' => 'non_client_event',
|
95
|
+
'channel' => 'private-test_channel',
|
96
|
+
'socket_id' => '8.422225',
|
97
|
+
'data' => { 'key' => 'value' }
|
98
|
+
}
|
99
|
+
|
100
|
+
Slanger::Webhook.expects(:post).never
|
101
|
+
|
102
|
+
channel.dispatch(message, 'private-test_channel')
|
103
|
+
end
|
104
|
+
end
|
69
105
|
end
|
@@ -6,8 +6,8 @@ describe Slanger::Api::RequestValidation do
|
|
6
6
|
it 'validation' do
|
7
7
|
socket_id = "POST\n/apps/99759/events\nauth_key=840543d97de9803651b1&auth_timestamp=123&auth_version=1.0&body_md5=some_md5&dummy="
|
8
8
|
|
9
|
-
expect {validate(nil) }.not_to
|
10
|
-
expect {validate("1234.123455") }.not_to raise_error
|
9
|
+
expect {validate(nil) }.not_to raise_error
|
10
|
+
expect {validate("1234.123455") }.not_to raise_error
|
11
11
|
|
12
12
|
expect {validate(socket_id) }.to raise_error Slanger::Api::InvalidRequest
|
13
13
|
expect {validate("something 123")}.to raise_error Slanger::Api::InvalidRequest
|
data/spec/unit/webhook_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe 'Slanger::Webhook' do
|
|
32
32
|
|
33
33
|
Slanger::Webhook.post name: 'channel_occupied', channel: 'test channel'
|
34
34
|
|
35
|
-
WebMock.
|
35
|
+
expect(WebMock).to have_requested(:post, Slanger::Config.webhook_url).
|
36
36
|
with(body: payload, headers: {
|
37
37
|
"X-Pusher-Key" => Slanger::Config.app_key,
|
38
38
|
"X-Pusher-Signature" => hmac,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slanger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stevie Graham
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-02-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -171,14 +171,14 @@ dependencies:
|
|
171
171
|
requirements:
|
172
172
|
- - "~>"
|
173
173
|
- !ruby/object:Gem::Version
|
174
|
-
version:
|
174
|
+
version: 3.6.0
|
175
175
|
type: :development
|
176
176
|
prerelease: false
|
177
177
|
version_requirements: !ruby/object:Gem::Requirement
|
178
178
|
requirements:
|
179
179
|
- - "~>"
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version:
|
181
|
+
version: 3.6.0
|
182
182
|
- !ruby/object:Gem::Dependency
|
183
183
|
name: pusher
|
184
184
|
requirement: !ruby/object:Gem::Requirement
|
@@ -369,8 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
369
369
|
- !ruby/object:Gem::Version
|
370
370
|
version: '0'
|
371
371
|
requirements: []
|
372
|
-
|
373
|
-
rubygems_version: 2.2.0
|
372
|
+
rubygems_version: 3.0.2
|
374
373
|
signing_key:
|
375
374
|
specification_version: 4
|
376
375
|
summary: A websocket service compatible with Pusher libraries
|
@@ -389,4 +388,3 @@ test_files:
|
|
389
388
|
- spec/unit/channel_spec.rb
|
390
389
|
- spec/unit/request_validation_spec.rb
|
391
390
|
- spec/unit/webhook_spec.rb
|
392
|
-
has_rdoc:
|