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 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