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