web-push 1.0.0
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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +30 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +183 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +356 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/setup +8 -0
- data/lib/tasks/web_push.rake +14 -0
- data/lib/web-push.rb +3 -0
- data/lib/web_push/encryption.rb +77 -0
- data/lib/web_push/errors.rb +29 -0
- data/lib/web_push/railtie.rb +9 -0
- data/lib/web_push/request.rb +189 -0
- data/lib/web_push/vapid_key.rb +105 -0
- data/lib/web_push/version.rb +5 -0
- data/lib/web_push.rb +80 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/web_push/encryption_spec.rb +95 -0
- data/spec/web_push/request_spec.rb +162 -0
- data/spec/web_push/vapid_key_spec.rb +66 -0
- data/spec/web_push_spec.rb +253 -0
- data/web-push.gemspec +25 -0
- metadata +183 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a165b29c06bb5d9a9aab0b65de25bd913ef7926909773485e97f0778bda4299d
|
4
|
+
data.tar.gz: c3f9727392a4049e27ac6bf83718749d5110cd290fa37718ee5b988d2c9c16e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca5db1201aa140ed1abe235d217183270b8b171d8b368ea7b5392c9cb04a2bf923c1c0e468788e1c2846dbd5c38bc32af53d427dbf307193ccaa00efbf6dd7d6
|
7
|
+
data.tar.gz: 8f179fd84cc0bd0f9e4899353d95af62e9e716552ae0bec86cdc7be2782056fcfb08b06a7efd3297e7468f1bb72ab6f5b16a29e31fc5ed0eb615117e790b8885
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require: rubocop-performance
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- 'bin/**/*'
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Max: 20
|
9
|
+
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Max: 100
|
12
|
+
|
13
|
+
Metrics/ModuleLength:
|
14
|
+
Max: 100
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/BlockLength:
|
20
|
+
Exclude:
|
21
|
+
- spec/**/*_spec.rb
|
22
|
+
|
23
|
+
Lint/AmbiguousBlockAssociation:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/Documentation:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Style/IndentHeredoc:
|
30
|
+
Enabled: false
|
data/.travis.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
env:
|
2
|
+
global:
|
3
|
+
- CC_TEST_REPORTER_ID=155202524386dfebe0c3267a5c868b5417ff4cc2cde8ed301fb36b177d46a458
|
4
|
+
language: ruby
|
5
|
+
rvm:
|
6
|
+
- 2.2
|
7
|
+
- 2.3
|
8
|
+
- 2.4
|
9
|
+
- 2.5
|
10
|
+
- 2.6
|
11
|
+
- 2.7
|
12
|
+
before_install:
|
13
|
+
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
14
|
+
- gem install bundler -v 1.17.3
|
15
|
+
before_script:
|
16
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
17
|
+
- chmod +x ./cc-test-reporter
|
18
|
+
- ./cc-test-reporter before-build
|
19
|
+
script: "bundle exec rake spec"
|
20
|
+
after_script:
|
21
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
22
|
+
addons:
|
23
|
+
code_climate:
|
24
|
+
repo_token: 155202524386dfebe0c3267a5c868b5417ff4cc2cde8ed301fb36b177d46a458
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [v1.1.0](https://github.com/zaru/webpush/tree/v1.1.0) (2020-11-16)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v1.0.0...v1.1.0)
|
6
|
+
|
7
|
+
**Merged pull requests:**
|
8
|
+
|
9
|
+
- Eliminate Ruby 2.7 warnings. [\#95](https://github.com/zaru/webpush/pull/95) ([morgoth](https://github.com/morgoth))
|
10
|
+
- set minimum ruby version is 2.2 [\#94](https://github.com/zaru/webpush/pull/94) ([Wolfer](https://github.com/Wolfer))
|
11
|
+
- Add proxy support [\#93](https://github.com/zaru/webpush/pull/93) ([Bugagazavr](https://github.com/Bugagazavr))
|
12
|
+
- fix syntax error [\#91](https://github.com/zaru/webpush/pull/91) ([tonytonyjan](https://github.com/tonytonyjan))
|
13
|
+
- change dependency gem versions [\#88](https://github.com/zaru/webpush/pull/88) ([zaru](https://github.com/zaru))
|
14
|
+
|
15
|
+
## [v1.0.0](https://github.com/zaru/webpush/tree/v1.0.0) (2019-08-15)
|
16
|
+
|
17
|
+
A stable version 1.0.0 has been released.
|
18
|
+
|
19
|
+
Thanks @mohamedhafez, @mplatov and @MedetaiAkaru for everything!
|
20
|
+
|
21
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.8...v1.0.0)
|
22
|
+
|
23
|
+
**Merged pull requests:**
|
24
|
+
|
25
|
+
- switch to aes128gcm encoding [\#84](https://github.com/zaru/webpush/pull/84) ([mohamedhafez](https://github.com/mohamedhafez))
|
26
|
+
- Fixed fcm spec [\#77](https://github.com/zaru/webpush/pull/77) ([zaru](https://github.com/zaru))
|
27
|
+
- add fcm endpoints [\#76](https://github.com/zaru/webpush/pull/76) ([MedetaiAkaru](https://github.com/MedetaiAkaru))
|
28
|
+
- Add Rubocop and fix [\#74](https://github.com/zaru/webpush/pull/74) ([zaru](https://github.com/zaru))
|
29
|
+
- Fix TravisCI bundler version [\#73](https://github.com/zaru/webpush/pull/73) ([zaru](https://github.com/zaru))
|
30
|
+
|
31
|
+
## [v0.3.8](https://github.com/zaru/webpush/tree/v0.3.8) (2019-04-16)
|
32
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.7...v0.3.8)
|
33
|
+
|
34
|
+
**Merged pull requests:**
|
35
|
+
|
36
|
+
- Fix authorization header [\#72](https://github.com/zaru/webpush/pull/72) ([xronos-i-am](https://github.com/xronos-i-am))
|
37
|
+
|
38
|
+
## [v0.3.7](https://github.com/zaru/webpush/tree/v0.3.7) (2019-03-06)
|
39
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.6...v0.3.7)
|
40
|
+
|
41
|
+
**Merged pull requests:**
|
42
|
+
|
43
|
+
- Add PEM support to import / export keys [\#65](https://github.com/zaru/webpush/pull/65) ([collimarco](https://github.com/collimarco))
|
44
|
+
|
45
|
+
## [v0.3.6](https://github.com/zaru/webpush/tree/v0.3.6) (2019-01-09)
|
46
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.5...v0.3.6)
|
47
|
+
|
48
|
+
**Merged pull requests:**
|
49
|
+
|
50
|
+
- Added a error class to arguments of raise\_error [\#62](https://github.com/zaru/webpush/pull/62) ([zaru](https://github.com/zaru))
|
51
|
+
- Fix TravisCI bundler version [\#61](https://github.com/zaru/webpush/pull/61) ([zaru](https://github.com/zaru))
|
52
|
+
- Raise Webpush::Unauthorized on HTTP 403 [\#59](https://github.com/zaru/webpush/pull/59) ([collimarco](https://github.com/collimarco))
|
53
|
+
|
54
|
+
## [v0.3.5](https://github.com/zaru/webpush/tree/v0.3.5) (2019-01-02)
|
55
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.4...v0.3.5)
|
56
|
+
|
57
|
+
**Merged pull requests:**
|
58
|
+
|
59
|
+
- Fix \#55 and \#51: raise the proper error based on the HTTP status code [\#58](https://github.com/zaru/webpush/pull/58) ([collimarco](https://github.com/collimarco))
|
60
|
+
- Add urgency option [\#57](https://github.com/zaru/webpush/pull/57) ([collimarco](https://github.com/collimarco))
|
61
|
+
- Add Rake task to generate VAPID keys [\#54](https://github.com/zaru/webpush/pull/54) ([stevenharman](https://github.com/stevenharman))
|
62
|
+
|
63
|
+
## [v0.3.4](https://github.com/zaru/webpush/tree/v0.3.4) (2018-05-25)
|
64
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.3...v0.3.4)
|
65
|
+
|
66
|
+
**Merged pull requests:**
|
67
|
+
|
68
|
+
- add http timeout options [\#50](https://github.com/zaru/webpush/pull/50) ([aishek](https://github.com/aishek))
|
69
|
+
|
70
|
+
## [v0.3.3](https://github.com/zaru/webpush/tree/v0.3.3) (2017-11-06)
|
71
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.2...v0.3.3)
|
72
|
+
|
73
|
+
**Merged pull requests:**
|
74
|
+
|
75
|
+
- Add typ to JWT header fields [\#46](https://github.com/zaru/webpush/pull/46) ([ykzts](https://github.com/ykzts))
|
76
|
+
- Specify the version of JWT strictly [\#45](https://github.com/zaru/webpush/pull/45) ([ykzts](https://github.com/ykzts))
|
77
|
+
|
78
|
+
## [v0.3.2](https://github.com/zaru/webpush/tree/v0.3.2) (2017-07-01)
|
79
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.1...v0.3.2)
|
80
|
+
|
81
|
+
**Merged pull requests:**
|
82
|
+
|
83
|
+
- feat: improve response error codes [\#39](https://github.com/zaru/webpush/pull/39) ([glennr](https://github.com/glennr))
|
84
|
+
- Update README.md [\#38](https://github.com/zaru/webpush/pull/38) ([kitaindia](https://github.com/kitaindia))
|
85
|
+
- Fix code example: Add close bracket [\#37](https://github.com/zaru/webpush/pull/37) ([kuranari](https://github.com/kuranari))
|
86
|
+
- fix code in README [\#36](https://github.com/zaru/webpush/pull/36) ([kuranari](https://github.com/kuranari))
|
87
|
+
- Minor fix in README: Close code blocks [\#32](https://github.com/zaru/webpush/pull/32) ([nicolas-fricke](https://github.com/nicolas-fricke))
|
88
|
+
- Copy edits for README clarifying GCM requirements [\#30](https://github.com/zaru/webpush/pull/30) ([rossta](https://github.com/rossta))
|
89
|
+
- Adding VAPID documentation [\#28](https://github.com/zaru/webpush/pull/28) ([rossta](https://github.com/rossta))
|
90
|
+
|
91
|
+
## [v0.3.1](https://github.com/zaru/webpush/tree/v0.3.1) (2016-10-24)
|
92
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.0...v0.3.1)
|
93
|
+
|
94
|
+
**Merged pull requests:**
|
95
|
+
|
96
|
+
- Bug fix invalid base64 [\#29](https://github.com/zaru/webpush/pull/29) ([rossta](https://github.com/rossta))
|
97
|
+
- Clarify VAPID usage further in README [\#27](https://github.com/zaru/webpush/pull/27) ([rossta](https://github.com/rossta))
|
98
|
+
|
99
|
+
## [v0.3.0](https://github.com/zaru/webpush/tree/v0.3.0) (2016-10-14)
|
100
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.5...v0.3.0)
|
101
|
+
|
102
|
+
**Merged pull requests:**
|
103
|
+
|
104
|
+
- Implement VAPID authorization [\#26](https://github.com/zaru/webpush/pull/26) ([rossta](https://github.com/rossta))
|
105
|
+
|
106
|
+
## [v0.2.5](https://github.com/zaru/webpush/tree/v0.2.5) (2016-09-14)
|
107
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.4...v0.2.5)
|
108
|
+
|
109
|
+
**Merged pull requests:**
|
110
|
+
|
111
|
+
- api key only needed for old google apis [\#24](https://github.com/zaru/webpush/pull/24) ([mohamedhafez](https://github.com/mohamedhafez))
|
112
|
+
|
113
|
+
## [v0.2.4](https://github.com/zaru/webpush/tree/v0.2.4) (2016-08-29)
|
114
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.3...v0.2.4)
|
115
|
+
|
116
|
+
**Merged pull requests:**
|
117
|
+
|
118
|
+
- VERIFY\_PEER by default - no need for a cert\_store option [\#20](https://github.com/zaru/webpush/pull/20) ([mohamedhafez](https://github.com/mohamedhafez))
|
119
|
+
|
120
|
+
## [v0.2.3](https://github.com/zaru/webpush/tree/v0.2.3) (2016-06-19)
|
121
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.2...v0.2.3)
|
122
|
+
|
123
|
+
**Merged pull requests:**
|
124
|
+
|
125
|
+
- detect and handle response errors [\#18](https://github.com/zaru/webpush/pull/18) ([mohamedhafez](https://github.com/mohamedhafez))
|
126
|
+
|
127
|
+
## [v0.2.2](https://github.com/zaru/webpush/tree/v0.2.2) (2016-06-13)
|
128
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.1...v0.2.2)
|
129
|
+
|
130
|
+
**Merged pull requests:**
|
131
|
+
|
132
|
+
- Don't include API key for firefox or other browsers [\#16](https://github.com/zaru/webpush/pull/16) ([mohamedhafez](https://github.com/mohamedhafez))
|
133
|
+
- Option to specify a cert store [\#15](https://github.com/zaru/webpush/pull/15) ([mohamedhafez](https://github.com/mohamedhafez))
|
134
|
+
- show ttl option in README [\#14](https://github.com/zaru/webpush/pull/14) ([mohamedhafez](https://github.com/mohamedhafez))
|
135
|
+
|
136
|
+
## [v0.2.1](https://github.com/zaru/webpush/tree/v0.2.1) (2016-05-23)
|
137
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.0...v0.2.1)
|
138
|
+
|
139
|
+
**Merged pull requests:**
|
140
|
+
|
141
|
+
- Make the response more detailed. [\#10](https://github.com/zaru/webpush/pull/10) ([kevinjom](https://github.com/kevinjom))
|
142
|
+
|
143
|
+
## [v0.2.0](https://github.com/zaru/webpush/tree/v0.2.0) (2016-05-16)
|
144
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.6...v0.2.0)
|
145
|
+
|
146
|
+
**Merged pull requests:**
|
147
|
+
|
148
|
+
- Make message payload optional [\#8](https://github.com/zaru/webpush/pull/8) ([rossta](https://github.com/rossta))
|
149
|
+
- Add specs [\#7](https://github.com/zaru/webpush/pull/7) ([rossta](https://github.com/rossta))
|
150
|
+
|
151
|
+
## [v0.1.6](https://github.com/zaru/webpush/tree/v0.1.6) (2016-05-12)
|
152
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.5...v0.1.6)
|
153
|
+
|
154
|
+
**Merged pull requests:**
|
155
|
+
|
156
|
+
- Add rake binstub [\#6](https://github.com/zaru/webpush/pull/6) ([rossta](https://github.com/rossta))
|
157
|
+
- Add syntax highlighting to README snippets [\#5](https://github.com/zaru/webpush/pull/5) ([rossta](https://github.com/rossta))
|
158
|
+
- Extract encryption module [\#4](https://github.com/zaru/webpush/pull/4) ([rossta](https://github.com/rossta))
|
159
|
+
- Add some happy case specs [\#3](https://github.com/zaru/webpush/pull/3) ([waheedel](https://github.com/waheedel))
|
160
|
+
|
161
|
+
## [v0.1.5](https://github.com/zaru/webpush/tree/v0.1.5) (2016-04-29)
|
162
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.4...v0.1.5)
|
163
|
+
|
164
|
+
**Merged pull requests:**
|
165
|
+
|
166
|
+
- add Ttl header parameter [\#1](https://github.com/zaru/webpush/pull/1) ([shouta-dev](https://github.com/shouta-dev))
|
167
|
+
|
168
|
+
## [v0.1.4](https://github.com/zaru/webpush/tree/v0.1.4) (2016-04-27)
|
169
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.3...v0.1.4)
|
170
|
+
|
171
|
+
## [v0.1.3](https://github.com/zaru/webpush/tree/v0.1.3) (2016-04-13)
|
172
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.2...v0.1.3)
|
173
|
+
|
174
|
+
## [v0.1.2](https://github.com/zaru/webpush/tree/v0.1.2) (2016-04-12)
|
175
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.1...v0.1.2)
|
176
|
+
|
177
|
+
## [v0.1.1](https://github.com/zaru/webpush/tree/v0.1.1) (2016-03-31)
|
178
|
+
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.0...v0.1.1)
|
179
|
+
|
180
|
+
## [v0.1.0](https://github.com/zaru/webpush/tree/v0.1.0) (2016-03-31)
|
181
|
+
|
182
|
+
|
183
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2016 Hiroyuki Sakuraba
|
2
|
+
Copyright (c) 2022 Marco Colli, Pushpad (https://pushpad.xyz)
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,356 @@
|
|
1
|
+
# WebPush
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/zaru/webpush)
|
4
|
+
[](https://codeclimate.com/github/zaru/webpush/coverage)
|
5
|
+
[](https://travis-ci.org/zaru/webpush)
|
6
|
+
[](https://badge.fury.io/rb/webpush)
|
7
|
+
|
8
|
+
This gem makes it possible to send push messages to web browsers from Ruby backends using the [Web Push Protocol](https://tools.ietf.org/html/draft-ietf-webpush-protocol-10). It supports [Message Encryption for Web Push](https://tools.ietf.org/html/draft-ietf-webpush-encryption) to send messages securely from server to user agent.
|
9
|
+
|
10
|
+
Payload is supported by Chrome 50+, Firefox 48+, Edge 79+.
|
11
|
+
|
12
|
+
[webpush Demo app here (building by Sinatra app).](https://github.com/zaru/webpush_demo_ruby)
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'web-push'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install web-push
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Sending a web push message to a visitor of your website requires a number of steps:
|
33
|
+
|
34
|
+
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.
|
35
|
+
2. A `manifest.json` file, linked from your user's page, identifies your app settings.
|
36
|
+
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.
|
37
|
+
4. Your server uses the `web-push` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
|
38
|
+
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.
|
39
|
+
|
40
|
+
### Generating VAPID keys
|
41
|
+
|
42
|
+
Use `web-push` to generate a VAPID key that has both a `public_key` and `private_key` attribute to be saved on the server side.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# One-time, on the server
|
46
|
+
vapid_key = WebPush.generate_key
|
47
|
+
|
48
|
+
# Save these in your application server settings
|
49
|
+
vapid_key.public_key
|
50
|
+
vapid_key.private_key
|
51
|
+
|
52
|
+
# Or you can save in PEM format if you prefer
|
53
|
+
vapid_key.to_pem
|
54
|
+
```
|
55
|
+
|
56
|
+
### Declaring manifest.json
|
57
|
+
|
58
|
+
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.
|
59
|
+
|
60
|
+
```javascript
|
61
|
+
{
|
62
|
+
"name": "My Website"
|
63
|
+
}
|
64
|
+
```
|
65
|
+
For Chrome web push, add the GCM sender id to a `manifest.json`.
|
66
|
+
|
67
|
+
```javascript
|
68
|
+
{
|
69
|
+
"name": "My Website",
|
70
|
+
"gcm_sender_id": "1006629465533"
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
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:
|
75
|
+
|
76
|
+
```html
|
77
|
+
<!-- index.html -->
|
78
|
+
<link rel="manifest" href="/manifest.json" />
|
79
|
+
```
|
80
|
+
|
81
|
+
### Installing a service worker
|
82
|
+
|
83
|
+
Your application javascript must register a service worker script at an appropriate scope (we're sticking with the root).
|
84
|
+
|
85
|
+
```javascript
|
86
|
+
// application.js
|
87
|
+
// Register the serviceWorker script at /serviceworker.js from your server if supported
|
88
|
+
if (navigator.serviceWorker) {
|
89
|
+
navigator.serviceWorker.register('/serviceworker.js')
|
90
|
+
.then(function(reg) {
|
91
|
+
console.log('Service worker change, registered the service worker');
|
92
|
+
});
|
93
|
+
}
|
94
|
+
// Otherwise, no push notifications :(
|
95
|
+
else {
|
96
|
+
console.error('Service worker is not supported in this browser');
|
97
|
+
}
|
98
|
+
```
|
99
|
+
|
100
|
+
### Subscribing to push notifications
|
101
|
+
|
102
|
+
#### With VAPID
|
103
|
+
|
104
|
+
The VAPID public key you generated earlier is made available to the client as a `UInt8Array`. To do this, one way would be to expose the urlsafe-decoded bytes from Ruby to JavaScript when rendering the HTML template. (Global variables used here for simplicity).
|
105
|
+
|
106
|
+
```javascript
|
107
|
+
window.vapidPublicKey = new Uint8Array(<%= Base64.urlsafe_decode64(ENV['VAPID_PUBLIC_KEY']).bytes %>);
|
108
|
+
```
|
109
|
+
|
110
|
+
Your application javascript uses the `navigator.serviceWorker.pushManager` to subscribe to push notifications, passing the VAPID public key to the subscription settings.
|
111
|
+
|
112
|
+
```javascript
|
113
|
+
// application.js
|
114
|
+
// When serviceWorker is supported, installed, and activated,
|
115
|
+
// subscribe the pushManager property with the vapidPublicKey
|
116
|
+
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
117
|
+
serviceWorkerRegistration.pushManager
|
118
|
+
.subscribe({
|
119
|
+
userVisibleOnly: true,
|
120
|
+
applicationServerKey: window.vapidPublicKey
|
121
|
+
});
|
122
|
+
});
|
123
|
+
```
|
124
|
+
|
125
|
+
#### Without VAPID
|
126
|
+
|
127
|
+
If you will not be sending VAPID details, then there is no need generate VAPID keys, and the `applicationServerKey` parameter may be omitted from the `pushManager.subscribe` call.
|
128
|
+
|
129
|
+
```javascript
|
130
|
+
// application.js
|
131
|
+
// When serviceWorker is supported, installed, and activated,
|
132
|
+
// subscribe the pushManager property with the vapidPublicKey
|
133
|
+
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
134
|
+
serviceWorkerRegistration.pushManager
|
135
|
+
.subscribe({
|
136
|
+
userVisibleOnly: true
|
137
|
+
});
|
138
|
+
});
|
139
|
+
```
|
140
|
+
|
141
|
+
### Triggering a web push notification
|
142
|
+
|
143
|
+
Hook into an client-side or backend event in your app to deliver a push message. The server must be made aware of the `subscription`. In the example below, we send the JSON generated subscription object to our backend at the "/push" endpoint with a message.
|
144
|
+
|
145
|
+
```javascript
|
146
|
+
// application.js
|
147
|
+
// Send the subscription and message from the client for the backend
|
148
|
+
// to set up a push notification
|
149
|
+
$(".web-push-button").on("click", (e) => {
|
150
|
+
navigator.serviceWorker.ready
|
151
|
+
.then((serviceWorkerRegistration) => {
|
152
|
+
serviceWorkerRegistration.pushManager.getSubscription()
|
153
|
+
.then((subscription) => {
|
154
|
+
$.post("/push", { subscription: subscription.toJSON(), message: "You clicked a button!" });
|
155
|
+
});
|
156
|
+
});
|
157
|
+
});
|
158
|
+
```
|
159
|
+
|
160
|
+
Imagine a Ruby app endpoint that responds to the request by triggering notification through the `web-push` gem.
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# app.rb
|
164
|
+
# Use the web-push gem API to deliver a push notiifcation merging
|
165
|
+
# the message, subscription values, and vapid options
|
166
|
+
post "/push" do
|
167
|
+
WebPush.payload_send(
|
168
|
+
message: params[:message],
|
169
|
+
endpoint: params[:subscription][:endpoint],
|
170
|
+
p256dh: params[:subscription][:keys][:p256dh],
|
171
|
+
auth: params[:subscription][:keys][:auth],
|
172
|
+
vapid: {
|
173
|
+
subject: "mailto:sender@example.com",
|
174
|
+
public_key: ENV['VAPID_PUBLIC_KEY'],
|
175
|
+
private_key: ENV['VAPID_PRIVATE_KEY']
|
176
|
+
},
|
177
|
+
ssl_timeout: 5, # value for Net::HTTP#ssl_timeout=, optional
|
178
|
+
open_timeout: 5, # value for Net::HTTP#open_timeout=, optional
|
179
|
+
read_timeout: 5 # value for Net::HTTP#read_timeout=, optional
|
180
|
+
)
|
181
|
+
end
|
182
|
+
```
|
183
|
+
|
184
|
+
Note: the VAPID options should be omitted if the client-side subscription was
|
185
|
+
generated without the `applicationServerKey` parameter described earlier. You
|
186
|
+
would instead pass the GCM api key along with the api request as shown in the
|
187
|
+
Usage section below.
|
188
|
+
|
189
|
+
### Receiving the push event
|
190
|
+
|
191
|
+
Your `/serviceworker.js` script may respond to `'push'` events. One action it can take is to trigger desktop notifications by calling `showNotification` on the `registration` property.
|
192
|
+
|
193
|
+
```javascript
|
194
|
+
// serviceworker.js
|
195
|
+
// The serviceworker context can respond to 'push' events and trigger
|
196
|
+
// notifications on the registration property
|
197
|
+
self.addEventListener("push", (event) => {
|
198
|
+
let title = (event.data && event.data.text()) || "Yay a message";
|
199
|
+
let body = "We have received a push message";
|
200
|
+
let tag = "push-simple-demo-notification-tag";
|
201
|
+
let icon = '/assets/my-logo-120x120.png';
|
202
|
+
|
203
|
+
event.waitUntil(
|
204
|
+
self.registration.showNotification(title, { body, icon, tag })
|
205
|
+
)
|
206
|
+
});
|
207
|
+
```
|
208
|
+
|
209
|
+
Before the notifications can be displayed, the user must grant permission for [notifications](https://developer.mozilla.org/en-US/docs/Web/API/notification) in a browser prompt, using something like the example below.
|
210
|
+
|
211
|
+
```javascript
|
212
|
+
// application.js
|
213
|
+
|
214
|
+
// Let's check if the browser supports notifications
|
215
|
+
if (!("Notification" in window)) {
|
216
|
+
console.error("This browser does not support desktop notification");
|
217
|
+
}
|
218
|
+
|
219
|
+
// Let's check whether notification permissions have already been granted
|
220
|
+
else if (Notification.permission === "granted") {
|
221
|
+
console.log("Permission to receive notifications has been granted");
|
222
|
+
}
|
223
|
+
|
224
|
+
// Otherwise, we need to ask the user for permission
|
225
|
+
else if (Notification.permission !== 'denied') {
|
226
|
+
Notification.requestPermission(function (permission) {
|
227
|
+
// If the user accepts, let's create a notification
|
228
|
+
if (permission === "granted") {
|
229
|
+
console.log("Permission to receive notifications has been granted");
|
230
|
+
}
|
231
|
+
});
|
232
|
+
}
|
233
|
+
```
|
234
|
+
|
235
|
+
If everything worked, you should see a desktop notification triggered via web
|
236
|
+
push. Yay!
|
237
|
+
|
238
|
+
Note: if you're using Rails, check out [serviceworker-rails](https://github.com/rossta/serviceworker-rails), a gem that makes it easier to host serviceworker scripts and manifest.json files at canonical endpoints (i.e., non-digested URLs) while taking advantage of the asset pipeline.
|
239
|
+
|
240
|
+
## API
|
241
|
+
|
242
|
+
### With a payload
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
message = {
|
246
|
+
title: "title",
|
247
|
+
body: "body",
|
248
|
+
icon: "http://example.com/icon.pn"
|
249
|
+
}
|
250
|
+
|
251
|
+
WebPush.payload_send(
|
252
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
253
|
+
message: JSON.generate(message),
|
254
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
255
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
256
|
+
ttl: 600, # optional, ttl in seconds, defaults to 2419200 (4 weeks)
|
257
|
+
urgency: 'normal' # optional, it can be very-low, low, normal, high, defaults to normal
|
258
|
+
)
|
259
|
+
```
|
260
|
+
|
261
|
+
### Without a payload
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
WebPush.payload_send(
|
265
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
266
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
267
|
+
auth: "aW1hcmthcmFpa3V6ZQ=="
|
268
|
+
)
|
269
|
+
```
|
270
|
+
|
271
|
+
### With VAPID
|
272
|
+
|
273
|
+
VAPID details are given as a hash with `:subject`, `:public_key`, and
|
274
|
+
`:private_key`. The `:subject` is a contact URI for the application server as either a "mailto:" or an "https:" address. The `:public_key` and `:private_key` should be passed as the base64-encoded values generated with `WebPush.generate_key`.
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
WebPush.payload_send(
|
278
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
279
|
+
message: "A message",
|
280
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
281
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
282
|
+
vapid: {
|
283
|
+
subject: "mailto:sender@example.com",
|
284
|
+
public_key: ENV['VAPID_PUBLIC_KEY'],
|
285
|
+
private_key: ENV['VAPID_PRIVATE_KEY']
|
286
|
+
}
|
287
|
+
)
|
288
|
+
```
|
289
|
+
|
290
|
+
### With VAPID in PEM format
|
291
|
+
|
292
|
+
This library also supports the PEM format for the VAPID keys:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
WebPush.payload_send(
|
296
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
297
|
+
message: "A message",
|
298
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
299
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
300
|
+
vapid: {
|
301
|
+
subject: "mailto:sender@example.com"
|
302
|
+
pem: ENV['VAPID_KEYS']
|
303
|
+
}
|
304
|
+
)
|
305
|
+
```
|
306
|
+
|
307
|
+
### With GCM api key
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
WebPush.payload_send(
|
311
|
+
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
312
|
+
message: "A message",
|
313
|
+
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
314
|
+
auth: "aW1hcmthcmFpa3V6ZQ==",
|
315
|
+
api_key: "<GCM API KEY>"
|
316
|
+
)
|
317
|
+
```
|
318
|
+
|
319
|
+
### ServiceWorker sample
|
320
|
+
|
321
|
+
see. https://github.com/zaru/web-push-sample
|
322
|
+
|
323
|
+
p256dh and auth generate sample code.
|
324
|
+
|
325
|
+
```javascript
|
326
|
+
navigator.serviceWorker.ready.then(function(sw) {
|
327
|
+
Notification.requestPermission(function(permission) {
|
328
|
+
if(permission !== 'denied') {
|
329
|
+
sw.pushManager.subscribe({userVisibleOnly: true}).then(function(s) {
|
330
|
+
var data = {
|
331
|
+
endpoint: s.endpoint,
|
332
|
+
p256dh: btoa(String.fromCharCode.apply(null, new Uint8Array(s.getKey('p256dh')))).replace(/\+/g, '-').replace(/\//g, '_'),
|
333
|
+
auth: btoa(String.fromCharCode.apply(null, new Uint8Array(s.getKey('auth')))).replace(/\+/g, '-').replace(/\//g, '_')
|
334
|
+
}
|
335
|
+
console.log(data);
|
336
|
+
});
|
337
|
+
}
|
338
|
+
});
|
339
|
+
});
|
340
|
+
```
|
341
|
+
|
342
|
+
payloads received sample code.
|
343
|
+
|
344
|
+
```javascript
|
345
|
+
self.addEventListener("push", function(event) {
|
346
|
+
var json = event.data.json();
|
347
|
+
self.registration.showNotification(json.title, {
|
348
|
+
body: json.body,
|
349
|
+
icon: json.icon
|
350
|
+
});
|
351
|
+
});
|
352
|
+
```
|
353
|
+
|
354
|
+
## Contributing
|
355
|
+
|
356
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/zaru/webpush.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "web_push"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|