webpush 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -11
- data/lib/webpush.rb +4 -2
- data/lib/webpush/errors.rb +15 -1
- data/lib/webpush/request.rb +9 -3
- data/lib/webpush/vapid_key.rb +18 -9
- data/lib/webpush/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94a1cc5374ad048519b130a97e805a863f682636
|
4
|
+
data.tar.gz: 43fda03427649b0fe51fd091859fe6cb32a9104a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e0efe569336570bce2edaf163f22d7fcfb7cfa3dcf6583297d062971d0ea338e58f1545a003f6cabea25243a739d61efa1c129db0d67ab07ec1908f9b612f1f
|
7
|
+
data.tar.gz: edbd2f55346dd918927ee512a4d8097641f934abc4df89f2598ee655650ccefe30eefda863207b319f574f0f7e441af36791b265023757c44fe424ce47f3111f
|
data/README.md
CHANGED
@@ -28,12 +28,11 @@ Or install it yourself as:
|
|
28
28
|
|
29
29
|
Sending a web push message to a visitor of your website requires a number of steps:
|
30
30
|
|
31
|
-
1. Your server has (optionally) generated (one-time) a set of [Voluntary Application server Identification (VAPID)](https://tools.ietf.org/html/draft-ietf-webpush-vapid-01) keys.
|
32
|
-
2.
|
33
|
-
3.
|
34
|
-
|
35
|
-
|
36
|
-
7. Your service worker is set up to receive `'push'` events. To trigger a desktop notification, the user has accepted the prompt to receive notifications from your site.
|
31
|
+
1. Your server has (optionally) generated (one-time) a set of [Voluntary Application server Identification (VAPID)](https://tools.ietf.org/html/draft-ietf-webpush-vapid-01) keys. Otherwise, to send messages through Chrome, you have registered your site through the [Google Developer Console](https://console.developers.google.com/) and have obtained a GCM sender id and GCM API key from your app settings.
|
32
|
+
2. A `manifest.json` file, linked from your user's page, identifies your app settings.
|
33
|
+
3. Also in the user's web browser, a `serviceWorker` is installed and activated and its `pushManager` property is subscribed to push events with your VAPID public key, with creates a `subscription` JSON object on the client side.
|
34
|
+
4. Your server uses the `webpush` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
|
35
|
+
5. Your service worker is set up to receive `'push'` events. To trigger a desktop notification, the user has accepted the prompt to receive notifications from your site.
|
37
36
|
|
38
37
|
### Generating VAPID keys
|
39
38
|
|
@@ -50,7 +49,14 @@ vapid_key.private_key
|
|
50
49
|
|
51
50
|
### Declaring manifest.json
|
52
51
|
|
53
|
-
|
52
|
+
Check out the [Web Manifest docs](https://developer.mozilla.org/en-US/docs/Web/Manifest) for details on what to include in your `manifest.json` file. If using VAPID, no app credentials are needed.
|
53
|
+
|
54
|
+
```javascript
|
55
|
+
{
|
56
|
+
"name": "My Website"
|
57
|
+
}
|
58
|
+
```
|
59
|
+
For Chrome web push, add the GCM sender id to a `manifest.json`.
|
54
60
|
|
55
61
|
```javascript
|
56
62
|
{
|
@@ -59,7 +65,7 @@ For Chrome web push, add the GCM sender id to a `manifest.json` file served at t
|
|
59
65
|
}
|
60
66
|
```
|
61
67
|
|
62
|
-
|
68
|
+
The file is served within the scope of your service worker script, like at the root, and link to it somewhere in the `<head>` tag:
|
63
69
|
|
64
70
|
```html
|
65
71
|
<!-- index.html -->
|
@@ -141,6 +147,7 @@ $(".webpush-button").on("click", (e) => {
|
|
141
147
|
.then((subscription) => {
|
142
148
|
$.post("/push", { subscription: subscription.toJSON(), message: "You clicked a button!" });
|
143
149
|
});
|
150
|
+
});
|
144
151
|
});
|
145
152
|
```
|
146
153
|
|
@@ -152,10 +159,10 @@ Imagine a Ruby app endpoint that responds to the request by triggering notificat
|
|
152
159
|
# the message, subscription values, and vapid options
|
153
160
|
post "/push" do
|
154
161
|
Webpush.payload_send(
|
155
|
-
message: params[:message]
|
162
|
+
message: params[:message],
|
156
163
|
endpoint: params[:subscription][:endpoint],
|
157
164
|
p256dh: params[:subscription][:keys][:p256dh],
|
158
|
-
auth: params[:subscription][:keys][:
|
165
|
+
auth: params[:subscription][:keys][:auth],
|
159
166
|
vapid: {
|
160
167
|
subject: "mailto:sender@example.com",
|
161
168
|
public_key: ENV['VAPID_PUBLIC_KEY'],
|
@@ -166,7 +173,9 @@ end
|
|
166
173
|
```
|
167
174
|
|
168
175
|
Note: the VAPID options should be omitted if the client-side subscription was
|
169
|
-
generated without the `applicationServerKey` parameter described earlier.
|
176
|
+
generated without the `applicationServerKey` parameter described earlier. You
|
177
|
+
would instead pass the GCM api key along with the api request as shown in the
|
178
|
+
Usage section below.
|
170
179
|
|
171
180
|
### Receiving the push event
|
172
181
|
|
@@ -266,6 +275,19 @@ Webpush.payload_send(
|
|
266
275
|
private_key: ENV['VAPID_PRIVATE_KEY']
|
267
276
|
}
|
268
277
|
)
|
278
|
+
```
|
279
|
+
|
280
|
+
### With GCM api key
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
Webpush.payload_send(
|
284
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
285
|
+
message: "A message",
|
286
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
287
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
288
|
+
api_key: "<GCM API KEY>"
|
289
|
+
)
|
290
|
+
```
|
269
291
|
|
270
292
|
### ServiceWorker sample
|
271
293
|
|
data/lib/webpush.rb
CHANGED
@@ -42,8 +42,10 @@ module Webpush
|
|
42
42
|
).perform
|
43
43
|
end
|
44
44
|
|
45
|
-
#
|
46
|
-
#
|
45
|
+
# Generate a VapidKey instance to obtain base64 encoded public and private keys
|
46
|
+
# suitable for VAPID protocol JSON web token signing
|
47
|
+
#
|
48
|
+
# @return [Webpush::VapidKey] a new VapidKey instance
|
47
49
|
def generate_key
|
48
50
|
VapidKey.new
|
49
51
|
end
|
data/lib/webpush/errors.rb
CHANGED
@@ -3,7 +3,21 @@ module Webpush
|
|
3
3
|
|
4
4
|
class ConfigurationError < Error; end
|
5
5
|
|
6
|
-
class ResponseError < Error;
|
6
|
+
class ResponseError < Error;
|
7
|
+
attr_reader :response, :host
|
8
|
+
|
9
|
+
def initialize(response, host)
|
10
|
+
@response = response
|
11
|
+
@host = host
|
12
|
+
super "host: #{host}, #{@response.inspect}\nbody:\n#{@response.body}"
|
13
|
+
end
|
14
|
+
end
|
7
15
|
|
8
16
|
class InvalidSubscription < ResponseError; end
|
17
|
+
|
18
|
+
class ExpiredSubscription < ResponseError; end
|
19
|
+
|
20
|
+
class PayloadTooLarge < ResponseError; end
|
21
|
+
|
22
|
+
class TooManyRequests < ResponseError; end
|
9
23
|
end
|
data/lib/webpush/request.rb
CHANGED
@@ -24,9 +24,15 @@ module Webpush
|
|
24
24
|
|
25
25
|
if resp.is_a?(Net::HTTPGone) || #Firefox unsubscribed response
|
26
26
|
(resp.is_a?(Net::HTTPBadRequest) && resp.message == "UnauthorizedRegistration") #Chrome unsubscribed response
|
27
|
-
raise InvalidSubscription.new(resp.
|
28
|
-
elsif
|
29
|
-
raise
|
27
|
+
raise InvalidSubscription.new(resp, uri.host)
|
28
|
+
elsif resp.is_a?(Net::HTTPNotFound) # 404
|
29
|
+
raise ExpiredSubscription.new(resp, uri.host)
|
30
|
+
elsif resp.is_a?(Net::HTTPRequestEntityTooLarge) # 413
|
31
|
+
raise PayloadTooLarge.new(resp, uri.host)
|
32
|
+
elsif resp.is_a?(Net::HTTPTooManyRequests) # 429, try again later!
|
33
|
+
raise TooManyRequests.new(resp, uri.host)
|
34
|
+
elsif !resp.is_a?(Net::HTTPSuccess) # unknown/unhandled response error
|
35
|
+
raise ResponseError.new(resp, uri.host)
|
30
36
|
end
|
31
37
|
|
32
38
|
resp
|
data/lib/webpush/vapid_key.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module Webpush
|
2
|
+
# Class for abstracting the generation and encoding of elliptic curve public and private keys for use with the VAPID protocol
|
3
|
+
#
|
4
|
+
# @attr_reader [OpenSSL::PKey::EC] :curve the OpenSSL elliptic curve instance
|
2
5
|
class VapidKey
|
6
|
+
# Create a VapidKey instance from encoded elliptic curve public and private keys
|
7
|
+
#
|
8
|
+
# @return [Webpush::VapidKey] a VapidKey instance for the given public and private keys
|
3
9
|
def self.from_keys(public_key, private_key)
|
4
10
|
key = new
|
5
11
|
key.public_key = public_key
|
@@ -15,30 +21,33 @@ module Webpush
|
|
15
21
|
@curve.generate_key
|
16
22
|
end
|
17
23
|
|
18
|
-
# Retrieve the encoded
|
19
|
-
#
|
24
|
+
# Retrieve the encoded elliptic curve public key for VAPID protocol
|
25
|
+
#
|
26
|
+
# @return [String] encoded binary representation of 65-byte VAPID public key
|
20
27
|
def public_key
|
21
28
|
encode64(curve.public_key.to_bn.to_s(2))
|
22
29
|
end
|
23
30
|
|
24
|
-
# Retrieve
|
25
|
-
#
|
31
|
+
# Retrieve the encoded elliptic curve public key suitable for the Web Push request
|
32
|
+
#
|
33
|
+
# @return [String] the encoded VAPID public key for us in 'Encryption' header
|
26
34
|
def public_key_for_push_header
|
27
35
|
trim_encode64(curve.public_key.to_bn.to_s(2))
|
28
36
|
end
|
29
37
|
|
30
|
-
#
|
31
|
-
#
|
38
|
+
# Retrive the encoded elliptic curve private key for VAPID protocol
|
39
|
+
#
|
40
|
+
# @return [String] base64 urlsafe-encoded binary representation of 32-byte VAPID private key
|
32
41
|
def private_key
|
33
|
-
|
42
|
+
encode64(curve.private_key.to_s(2))
|
34
43
|
end
|
35
44
|
|
36
45
|
def public_key=(key)
|
37
|
-
|
46
|
+
curve.public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(key))
|
38
47
|
end
|
39
48
|
|
40
49
|
def private_key=(key)
|
41
|
-
|
50
|
+
curve.private_key = to_big_num(key)
|
42
51
|
end
|
43
52
|
|
44
53
|
def curve_name
|
data/lib/webpush/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webpush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zaru@sakuraba
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hkdf
|