viaduct-webpush 1.0.3 → 1.0.4
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/Gemfile +3 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/lib/viaduct/web_push/channel.rb +40 -2
- data/lib/viaduct/web_push/web_socket/channel.rb +80 -0
- data/lib/viaduct/web_push/web_socket/connection.rb +190 -0
- data/lib/viaduct/web_push/web_socket/raw_socket.rb +77 -0
- data/lib/viaduct/web_push/web_socket.rb +40 -0
- data/lib/viaduct/web_push.rb +10 -1
- data/lib/viaduct/webpush/websocket.rb +1 -0
- metadata +51 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79f4047fad65b0886d126655ce6ed34a0570028f
|
4
|
+
data.tar.gz: e375862818d3424875da28e003686396902de8c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e0ed7ae59ed0895f75c92f1ec7c97a8c0d1ab404acc215ad042358ed7f3bc48a2a652af3148b814b2a7fb272928621a8fab3ae0e18612301975aaea2b961f1c
|
7
|
+
data.tar.gz: be83004eff45e0b50a89b6b696093c8c982051371ba8425872edef4ded2924fcb2d1c5571e817fecb8be11add2a8d5d0abc4a463970019d5f4eb5da82e912bb0
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -14,12 +14,24 @@ gem 'viaduct-webpush', :require => 'viaduct/webpush'
|
|
14
14
|
|
15
15
|
## Usage
|
16
16
|
|
17
|
+
### Configuration
|
18
|
+
|
17
19
|
```ruby
|
18
20
|
require 'viaduct/webpush'
|
19
21
|
|
20
22
|
Viaduct::WebPush.token = 'your-token'
|
21
23
|
Viaduct::WebPush.secret = 'your-secret'
|
22
24
|
|
25
|
+
# Additional configuration for websockets
|
26
|
+
require 'viaduct/webpush/websocket'
|
27
|
+
Viaduct::WebPush::WebSocket.logger = Your.logger # optional
|
28
|
+
```
|
29
|
+
|
30
|
+
### Sending Messages via the HTTP API
|
31
|
+
|
32
|
+
Sending messages via the HTTP API is ideal if you're sending low-frequency messages and when you don't need to receive any messages in return.
|
33
|
+
|
34
|
+
```ruby
|
23
35
|
# Sending a single message
|
24
36
|
Viaduct::WebPush['test-channel'].trigger('say-hello', {
|
25
37
|
:name => 'Adam'
|
@@ -33,3 +45,51 @@ Viaduct::WebPush::Channel.multi_trigger(['channel1', 'channel2'], 'say-hello', {
|
|
33
45
|
# Generating a signature for private channels
|
34
46
|
Viaduct::WebPush::Channel.generate_signature(session_id, channel_name)
|
35
47
|
```
|
48
|
+
|
49
|
+
### Sending and Receiving via the Websockets API
|
50
|
+
|
51
|
+
If you want to receive data from Viaduct WebPush, or you plan on sending messages very frequently, you'll want to use the websockets API.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# Ensure you've included the websockets classes
|
55
|
+
require 'viaduct/webpush/websocket'
|
56
|
+
|
57
|
+
# Connect to the VWP service
|
58
|
+
connection = Viaduct::WebPush::WebSocket.connection
|
59
|
+
|
60
|
+
# Subscribe to any channels you want to send/recieve on
|
61
|
+
channel1 = connection.subscribe('channel1')
|
62
|
+
|
63
|
+
# Bind a handler to a specific event that comes in on a channel
|
64
|
+
channel1.bind 'say-hello' do |received_data|
|
65
|
+
puts received_data # deserialized JSON
|
66
|
+
end
|
67
|
+
|
68
|
+
# Send messages out on a channel
|
69
|
+
channel1.trigger('say-hello', {
|
70
|
+
:name => "Adam"
|
71
|
+
})
|
72
|
+
|
73
|
+
# Disconnect from VWP when you're done
|
74
|
+
connection.disconnect
|
75
|
+
|
76
|
+
# Reconnect if you need to later
|
77
|
+
connection.connect
|
78
|
+
```
|
79
|
+
|
80
|
+
You can also choose not authenticate if you only want to receive messages, or not to automatically connect if you want to set up all of your bindings before connecting.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# Do not authenticate, gives you a receive-only connection
|
84
|
+
connection = Viaduct::WebPush::WebSocket.connection(:authenticate => false)
|
85
|
+
|
86
|
+
# Do not automatically connect, set up your bindings first
|
87
|
+
connection = Viaduct::WebPush::WebSocket.connection(:autoconnect => false)
|
88
|
+
|
89
|
+
channel1 = connection.subscribe('channel1')
|
90
|
+
channel1.bind 'say-hello' do |received_data|
|
91
|
+
puts received_data
|
92
|
+
end
|
93
|
+
|
94
|
+
connection.connect
|
95
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -1,9 +1,23 @@
|
|
1
|
+
# Class for sending messages to viaduct via the HTTP API
|
2
|
+
|
1
3
|
module Viaduct
|
2
4
|
module WebPush
|
3
5
|
class Channel
|
4
6
|
|
5
|
-
|
7
|
+
attr_accessor :subscribed, :name, :bindings
|
8
|
+
|
9
|
+
def initialize(name, connection)
|
6
10
|
@name = name
|
11
|
+
@connection = connection
|
12
|
+
@bindings = Hash.new([])
|
13
|
+
@subscribed = false
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Blank name indicates global channel
|
18
|
+
#
|
19
|
+
def global?
|
20
|
+
@name.nil?
|
7
21
|
end
|
8
22
|
|
9
23
|
#
|
@@ -22,6 +36,31 @@ module Viaduct
|
|
22
36
|
end
|
23
37
|
end
|
24
38
|
|
39
|
+
#
|
40
|
+
# Bind some code to an incoming message on this channel
|
41
|
+
#
|
42
|
+
def bind(event, &block)
|
43
|
+
@bindings[event] += [block]
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Run the bindings for an event
|
48
|
+
#
|
49
|
+
def dispatch(event, data)
|
50
|
+
@bindings[event].each do |binding|
|
51
|
+
binding.call(data)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Send request subscription for this channel from VWP
|
57
|
+
#
|
58
|
+
def register
|
59
|
+
return if @subscibed || global?
|
60
|
+
signature = self.class.generate_signature(@connection.session_id, @name)
|
61
|
+
@connection.register_subscription(@name, signature)
|
62
|
+
end
|
63
|
+
|
25
64
|
#
|
26
65
|
# Trigger a single even on a given channel
|
27
66
|
#
|
@@ -29,7 +68,6 @@ module Viaduct
|
|
29
68
|
WebPush.request('trigger', {:channel => channel, :event => event, :data => data.to_json})
|
30
69
|
end
|
31
70
|
|
32
|
-
|
33
71
|
#
|
34
72
|
# Trigger an event on multiple channels simultaneously
|
35
73
|
#
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Viaduct
|
2
|
+
module WebPush
|
3
|
+
module WebSocket
|
4
|
+
class Channel
|
5
|
+
|
6
|
+
attr_accessor :subscribed, :name, :bindings
|
7
|
+
|
8
|
+
def initialize(name, connection)
|
9
|
+
@name = name
|
10
|
+
@connection = connection
|
11
|
+
@bindings = Hash.new([])
|
12
|
+
@subscribed = false
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Blank name indicates global channel
|
17
|
+
#
|
18
|
+
def global?
|
19
|
+
@name.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Bind some code to an incoming message on this channel
|
24
|
+
#
|
25
|
+
def bind(event, &block)
|
26
|
+
@bindings[event] += [block]
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Run the bindings for an event
|
31
|
+
#
|
32
|
+
def dispatch(event, data)
|
33
|
+
@bindings[event].each do |binding|
|
34
|
+
binding.call(data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Send request subscription for this channel from VWP
|
40
|
+
#
|
41
|
+
def register
|
42
|
+
return if @subscibed || global?
|
43
|
+
|
44
|
+
if @name =~ /^private-/
|
45
|
+
signature = self.class.generate_signature(@connection.session_id, @name)
|
46
|
+
else
|
47
|
+
signature = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
@connection.register_subscription(@name, signature)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Trigger an event on this channel
|
55
|
+
#
|
56
|
+
def trigger(event, data = {})
|
57
|
+
@connection.trigger(@name, event, data)
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
String.new.tap do |s|
|
62
|
+
s << "#<#{self.class.name}:#{self.object_id} "
|
63
|
+
s << [:name, :subscribed].map do |attrib|
|
64
|
+
"#{attrib}: #{self.send(attrib).inspect}"
|
65
|
+
end.join(', ')
|
66
|
+
s << ">"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Generate a HMAC signature for private channels
|
72
|
+
#
|
73
|
+
def self.generate_signature(session_id, channel)
|
74
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, WebPush.secret, "#{session_id}:#{channel}")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module Viaduct
|
2
|
+
module WebPush
|
3
|
+
module WebSocket
|
4
|
+
class Connection
|
5
|
+
|
6
|
+
attr_reader :connected, :session_id, :channels, :authenticated
|
7
|
+
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
:authenticate => true,
|
10
|
+
:autoconnect => true
|
11
|
+
}
|
12
|
+
|
13
|
+
def initialize(options={})
|
14
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
15
|
+
|
16
|
+
@connected = false
|
17
|
+
@authenticated = false
|
18
|
+
@session_id = nil
|
19
|
+
@channels = {}
|
20
|
+
@logger = WebSocket.logger
|
21
|
+
|
22
|
+
# Set up global vwp events
|
23
|
+
@global_channel = subscribe(nil)
|
24
|
+
|
25
|
+
# On connect, store data from the payload, send vwp:subscribe events
|
26
|
+
# for each channel that's already been addded
|
27
|
+
@global_channel.bind 'vwp:connected' do |data|
|
28
|
+
@logger.info "Connected to vwp"
|
29
|
+
|
30
|
+
@global_channel.subscribed = true
|
31
|
+
@session_id = data["session_id"]
|
32
|
+
@connected = true
|
33
|
+
|
34
|
+
register_subscriptions
|
35
|
+
end
|
36
|
+
|
37
|
+
# If we're sending messages we need to authenticate after we've connected to vwp
|
38
|
+
if @options[:authenticate]
|
39
|
+
@global_channel.bind 'vwp:connected' do
|
40
|
+
authenticate
|
41
|
+
end
|
42
|
+
@global_channel.bind 'vwp:authenticated' do
|
43
|
+
@logger.info "Authenticated with vwp"
|
44
|
+
@authenticated = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# When we've successfully subscribed to a channel set the subscribed bit to true on the channel
|
49
|
+
@global_channel.bind 'vwp:subscribed' do |data|
|
50
|
+
channel_id = data['channel']
|
51
|
+
@channels[channel_id].subscribed = true
|
52
|
+
@logger.info "Subscribed to vwp #{data['channel_name']}"
|
53
|
+
end
|
54
|
+
|
55
|
+
connect if @options[:autoconnect]
|
56
|
+
end
|
57
|
+
|
58
|
+
def [](channel_name)
|
59
|
+
@channels[channel_name]
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Create a new channel object and send a vwp:subscribe event if we're
|
64
|
+
# already connected to vwp
|
65
|
+
#
|
66
|
+
def subscribe(channel_name)
|
67
|
+
@channels[channel_name] ||= Channel.new(channel_name, self)
|
68
|
+
@channels[channel_name].register if @connected
|
69
|
+
@channels[channel_name]
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Create a new thread and connect to vwp in it.
|
74
|
+
# Create an event loop for the thread which will dispatch incoming messages
|
75
|
+
#
|
76
|
+
def connect
|
77
|
+
return if @websocket
|
78
|
+
@logger.debug "Connecting..."
|
79
|
+
|
80
|
+
Thread.abort_on_exception = true
|
81
|
+
@websocket_thread = Thread.new do
|
82
|
+
@websocket = RawSocket.new
|
83
|
+
loop do
|
84
|
+
@websocket.receive.each do |message|
|
85
|
+
data = JSON.parse(message)
|
86
|
+
@logger.debug data
|
87
|
+
dispatch(data)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Disconnect the websocket server and reset all variables, set all channels
|
97
|
+
# as unsubscribed
|
98
|
+
#
|
99
|
+
def disconnect
|
100
|
+
@websocket.disconnect
|
101
|
+
@websocket = nil
|
102
|
+
@websocket_thread.kill
|
103
|
+
@websocket_thread = nil
|
104
|
+
@connected = false
|
105
|
+
@session_id = nil
|
106
|
+
@channels.each {|name, chan| chan.subscribed = false }
|
107
|
+
@logger.info "Disconnected from vwp"
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Build a vwp message and send it via the websocket
|
112
|
+
#
|
113
|
+
def trigger(channel_name, event, data)
|
114
|
+
return false unless @authenticated
|
115
|
+
|
116
|
+
payload = JSON.generate({
|
117
|
+
"event" => "vwp:send",
|
118
|
+
"data" => {
|
119
|
+
"channel" => channel_name,
|
120
|
+
"event" => event,
|
121
|
+
"data" => data
|
122
|
+
}
|
123
|
+
})
|
124
|
+
|
125
|
+
@websocket.send_data(payload)
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Send a vwp:subscribe message via the websocket. The socket name and signature
|
131
|
+
# are calculated by the Channel
|
132
|
+
#
|
133
|
+
def register_subscription(channel_name, signature)
|
134
|
+
payload = JSON.generate({"event" => "vwp:subscribe", "data" => {
|
135
|
+
"channel" => channel_name,
|
136
|
+
"signature" => signature
|
137
|
+
}})
|
138
|
+
@websocket.send_data(payload)
|
139
|
+
end
|
140
|
+
|
141
|
+
def inspect
|
142
|
+
String.new.tap do |s|
|
143
|
+
s << "#<#{self.class.name}:#{self.object_id} "
|
144
|
+
s << [:connected, :session_id, :channels].map do |attrib|
|
145
|
+
"#{attrib}: #{self.send(attrib).inspect}"
|
146
|
+
end.join(', ')
|
147
|
+
s << ">"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
protected
|
152
|
+
|
153
|
+
#
|
154
|
+
# Process some payload data and dispatch the message to the relevant
|
155
|
+
# channel. The channel will then dispatch the data to the correct binding.
|
156
|
+
#
|
157
|
+
def dispatch(payload_data)
|
158
|
+
event = payload_data['event']
|
159
|
+
channel = payload_data['channel']
|
160
|
+
data = payload_data['data']
|
161
|
+
|
162
|
+
if @channels[channel]
|
163
|
+
@channels[channel].dispatch(event, data)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Send a vwp:subscribe message for every channel
|
168
|
+
def register_subscriptions
|
169
|
+
@channels.each do |name, chan|
|
170
|
+
chan.register
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# Send a vwp:authenticate message that we need if we're going to be sending data
|
176
|
+
# on the websocket.
|
177
|
+
#
|
178
|
+
def authenticate
|
179
|
+
@logger.debug "Authenticating..."
|
180
|
+
|
181
|
+
payload = JSON.generate({"event" => "vwp:authenticate", "data" => {
|
182
|
+
"secret" => Viaduct::WebPush.secret
|
183
|
+
}})
|
184
|
+
@websocket.send_data(payload)
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Viaduct
|
2
|
+
module WebPush
|
3
|
+
module WebSocket
|
4
|
+
class RawSocket
|
5
|
+
|
6
|
+
WAIT_EXCEPTIONS = [Errno::EWOULDBLOCK, Errno::EAGAIN, IO::WaitReadable]
|
7
|
+
|
8
|
+
#
|
9
|
+
# Open an SSL connection and perform the HTTP upgrade/websockets handhsake procedure
|
10
|
+
#
|
11
|
+
def initialize
|
12
|
+
@handshake = ::WebSocket::Handshake::Client.new(:url => Viaduct::WebPush::WebSocket.endpoint)
|
13
|
+
@connection = TCPSocket.new(@handshake.host, @handshake.port || 443)
|
14
|
+
|
15
|
+
ssl_ctx = OpenSSL::SSL::SSLContext.new
|
16
|
+
ssl_ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
17
|
+
ssl_ctx.cert_store = OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
|
18
|
+
|
19
|
+
ssl = OpenSSL::SSL::SSLSocket.new(@connection, ssl_ctx)
|
20
|
+
ssl.sync_close = true
|
21
|
+
ssl.connect
|
22
|
+
|
23
|
+
@connection = ssl
|
24
|
+
|
25
|
+
@connection.write @handshake.to_s
|
26
|
+
@connection.flush
|
27
|
+
|
28
|
+
while line = @connection.gets
|
29
|
+
@handshake << line
|
30
|
+
break if @handshake.finished?
|
31
|
+
end
|
32
|
+
|
33
|
+
raise HandshakeError unless @handshake.valid?
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Send a websocket frame out on the connection
|
38
|
+
#
|
39
|
+
def send_data(message, type=:text)
|
40
|
+
frame = ::WebSocket::Frame::Outgoing::Client.new(:version => @handshake.version, :data => message, :type => type)
|
41
|
+
@connection.write frame.to_s
|
42
|
+
@connection.flush
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Read data from the socket and wait with IO#select
|
47
|
+
#
|
48
|
+
def receive
|
49
|
+
frame = ::WebSocket::Frame::Incoming::Server.new(:version => @handshake.version)
|
50
|
+
|
51
|
+
begin
|
52
|
+
data = @connection.read_nonblock(1024)
|
53
|
+
rescue *WAIT_EXCEPTIONS
|
54
|
+
IO.select([@connection])
|
55
|
+
retry
|
56
|
+
end
|
57
|
+
frame << data
|
58
|
+
|
59
|
+
messages = []
|
60
|
+
while message = frame.next
|
61
|
+
messages << message.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
messages
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Close the connection
|
69
|
+
#
|
70
|
+
def disconnect
|
71
|
+
@connection.close
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'websocket'
|
3
|
+
require 'viaduct/web_push/web_socket/raw_socket'
|
4
|
+
require 'viaduct/web_push/web_socket/connection'
|
5
|
+
require 'viaduct/web_push/web_socket/channel'
|
6
|
+
|
7
|
+
module Viaduct
|
8
|
+
module WebPush
|
9
|
+
module WebSocket
|
10
|
+
|
11
|
+
class HandshakeError < StandardError; end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
attr_writer :logger
|
16
|
+
attr_writer :endpoint
|
17
|
+
|
18
|
+
#
|
19
|
+
# Initialize a websocket connection for sending and receiving messages
|
20
|
+
#
|
21
|
+
def connection(options={})
|
22
|
+
@connection ||= Connection.new(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Return the endpoint for the websocket server
|
27
|
+
#
|
28
|
+
def endpoint
|
29
|
+
@endpoint ||= "wss://#{Viaduct::WebPush.webpush_host}/vwp/socket/#{Viaduct::WebPush.token}"
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def logger
|
34
|
+
@logger ||= Logger.new(STDOUT)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/viaduct/web_push.rb
CHANGED
@@ -10,11 +10,18 @@ module Viaduct
|
|
10
10
|
|
11
11
|
class << self
|
12
12
|
|
13
|
+
#
|
14
|
+
# Return the host for the VWP service
|
15
|
+
#
|
16
|
+
def webpush_host
|
17
|
+
@webpush_host ||= 'webpush.viaduct.io'
|
18
|
+
end
|
19
|
+
|
13
20
|
#
|
14
21
|
# Return the endpoint for API request
|
15
22
|
#
|
16
23
|
def endpoint
|
17
|
-
@endpoint ||=
|
24
|
+
@endpoint ||= "https://#{self.webpush_host}/vwp/api"
|
18
25
|
end
|
19
26
|
|
20
27
|
#
|
@@ -34,6 +41,7 @@ module Viaduct
|
|
34
41
|
#
|
35
42
|
# Allow some configuration to be overridden/set
|
36
43
|
#
|
44
|
+
attr_writer :webpush_host
|
37
45
|
attr_writer :endpoint
|
38
46
|
attr_writer :token
|
39
47
|
attr_writer :secret
|
@@ -46,6 +54,7 @@ module Viaduct
|
|
46
54
|
@channels[name] ||= Channel.new(name)
|
47
55
|
end
|
48
56
|
|
57
|
+
|
49
58
|
#
|
50
59
|
# Make an HTTP request to the WebPush API
|
51
60
|
#
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'viaduct/web_push/web_socket'
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viaduct-webpush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: json
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -30,6 +58,20 @@ dependencies:
|
|
30
58
|
- - "<"
|
31
59
|
- !ruby/object:Gem::Version
|
32
60
|
version: '2'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: websocket
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.2'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.2'
|
33
75
|
description: A client library allows messages to be sent to the WebPush API.
|
34
76
|
email:
|
35
77
|
- adam@viaduct.io
|
@@ -37,10 +79,17 @@ executables: []
|
|
37
79
|
extensions: []
|
38
80
|
extra_rdoc_files: []
|
39
81
|
files:
|
82
|
+
- Gemfile
|
40
83
|
- README.md
|
84
|
+
- Rakefile
|
41
85
|
- lib/viaduct/web_push.rb
|
42
86
|
- lib/viaduct/web_push/channel.rb
|
87
|
+
- lib/viaduct/web_push/web_socket.rb
|
88
|
+
- lib/viaduct/web_push/web_socket/channel.rb
|
89
|
+
- lib/viaduct/web_push/web_socket/connection.rb
|
90
|
+
- lib/viaduct/web_push/web_socket/raw_socket.rb
|
43
91
|
- lib/viaduct/webpush.rb
|
92
|
+
- lib/viaduct/webpush/websocket.rb
|
44
93
|
homepage: http://viaduct.io
|
45
94
|
licenses:
|
46
95
|
- MIT
|
@@ -66,4 +115,3 @@ signing_key:
|
|
66
115
|
specification_version: 4
|
67
116
|
summary: A client library for the Viaduct WebPush API.
|
68
117
|
test_files: []
|
69
|
-
has_rdoc:
|