webpush 0.3.1 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18e5c11503abaf7212ca277dd336ae64dfede00f
4
- data.tar.gz: 10fc83dcbc3f7deb76c1a53e76e031b68aac989c
3
+ metadata.gz: 94a1cc5374ad048519b130a97e805a863f682636
4
+ data.tar.gz: 43fda03427649b0fe51fd091859fe6cb32a9104a
5
5
  SHA512:
6
- metadata.gz: f8a099a95fc658ccc3fa5c84b75e142c65e5b0f34f81c78955c1116b4b6f6c8f83d961c288cacf90b40a7fe0aa6902a235e01af2d3d4f8352b94e97e66f32feb
7
- data.tar.gz: e468dd4c140e9e925979e20d27add5c1c74d5e6c49ecbf6ac24260147fc0ceb2a92ec636e6d6905a45fca801851620b5328992c52dca0faaf2a89e833ace9d62
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. 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. For using Google's deprecated GCM protocol instead of VAPID, a separate GCM API key from your app settings would also be necessary.
33
- 3. A `manifest.json` file, linked from your user's page, identifies your app settings, including the GCM sender ID.
34
- 5. 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.
35
- 6. Your server uses the `webpush` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
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
- For Chrome web push, add the GCM sender id to a `manifest.json` file served at the scope of your app (or above), like at the root.
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
- And link to it somewhere in the `<head>` tag:
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][:p256dh],
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
 
@@ -42,8 +42,10 @@ module Webpush
42
42
  ).perform
43
43
  end
44
44
 
45
- # public_key: vapid_key.public_key.to_bn.to_s(2)
46
- # private_key: vapid_key.private_key.to_s(2)
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
@@ -3,7 +3,21 @@ module Webpush
3
3
 
4
4
  class ConfigurationError < Error; end
5
5
 
6
- class ResponseError < Error; end
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
@@ -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.inspect)
28
- elsif !resp.is_a?(Net::HTTPSuccess) #unknown/unhandled response error
29
- raise ResponseError.new "host: #{uri.host}, #{resp.inspect}\nbody:\n#{resp.body}"
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
@@ -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 EC public key for server-side storage
19
- # @return encoded binary representaion of 65-byte VAPID public key
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 EC public key for Web Push
25
- # @return the encoded VAPID public key suitable for Web Push transport
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
- # Convenience
31
- # @return base64 urlsafe-encoded binary representaion of 32-byte VAPID private key
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
- Webpush.encode64(curve.private_key.to_s(2))
42
+ encode64(curve.private_key.to_s(2))
34
43
  end
35
44
 
36
45
  def public_key=(key)
37
- @curve.public_key = OpenSSL::PKey::EC::Point.new(group, to_big_num(key))
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
- @curve.private_key = to_big_num(key)
50
+ curve.private_key = to_big_num(key)
42
51
  end
43
52
 
44
53
  def curve_name
@@ -1,3 +1,3 @@
1
1
  module Webpush
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
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.1
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: 2016-10-24 00:00:00.000000000 Z
11
+ date: 2017-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hkdf