はじめに
かつては、gcm_sender_idが必要だったりと事前登録が必要で面倒だった、Service Workerを用いたWeb Pushですが、VAPIDという仕組みの出現によって、事前登録なしにWeb Pushを行うことができるようになりました。
これによって、僕自身、実装のモチベーションが上がりました。が、しかし、謎の400エラーに悩まされたりしたので、同じ苦しみを味わっている人たちへの何かしらになればとここに書き残します。
VAPIDを用いたWeb Pushの手順等は、書いてくださっている方がいらしたので、
GCMの登録が不要になったChromeのWeb Pushを試してみる
こちらを参考にすると幸福かもしれません。
また、Server側の処理に関しては、web-pushというライブラリがかなり参考になります。
https://github.com/web-push-libs/web-push/
自分で1から実装したい場合は、このコードを参考にするとよいかもしれません。
かなり雑ではありますが、node の web-pushを用いた簡単なサンプルに関しては
https://github.com/kanataxa/webpushtest
こちらに上げました。かなり雑かつシンプルなので、ほんのちょっとの参考程度に。
また、Service WorkerのActivate等のタイミングなどは知っておいた方が良いと思います。
Service Workerの紹介
こちらが簡単かつ非常に分かりやすかったので参考にしてください。
英語ではありますが、簡単にWeb Push の体験をしたい場合は、こちらを使うと幸せです。
Adding Push Notifications to a Web App
以下は、僕がやっていて悲しくなったことです。
web-push libraryのこと
単純に、ソースコード諸々読むの怠っただけなんですが。
最初始めたときに色々なサイトを参考にしてごちゃごちゃ書いてしまって嵌っただけです。
nodejsで web-pushのライブラリを使う方がいらっしゃったら参考にしてください。
上で紹介させて頂いた記事にも書いてありますが、ざっくり雑に言うとVAPIDを用いる場合は、
サーバの共通鍵とJWTを用いた暗号的な云々で検証等を行います。
・subscribe()時にアプリケーションサーバの公開鍵を含めて登録する。
・Pushサーバの認証のために,Push通知のリクエストをアプリケーションサーバがPushサーバに行う際に、JWTが必要になる。
ここで、web-push libraryは非常に便利で、これらのことを勝手にやってくれます。
どういうことかというと、GithubのREADMEに色々書いてありますが、
webpush.sendNotification()にきちんと正しい引数を与えれば、それだけで終わります。
JWTもこいつが勝手に作ってくれるので、まったく気にする必要がありません。
足りなければErrorを投げてくれます。
悲しい400エラー
webpush.sendNotification()で発生したエラーなんですが。
これソース追うと、PushServerからのレスポンスのエラーをCatchしているようです、たしか。(うろ覚え)
name: 'WebPushError',
message: 'Received unexpected response code',
statusCode: 400,
headers:
{ 'content-type': 'text/html; charset=UTF-8',
date: 'Thu, 26 Jan 2017 10:57:59 GMT',
expires: 'Thu, 26 Jan 2017 10:57:59 GMT',
'cache-control': 'private, max-age=0',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block',
server: 'GSE',
'alt-svc': 'quic=":443"; ma=2592000; v="35,34"',
'accept-ranges': 'none',
vary: 'Accept-Encoding',
connection: 'close' },..........
こんな感じのエラーですね。
400エラーなのでサーバがPushサーバに送る際にミスってるのかなぁと思って嵌ったんですが、
どうやらpushManager.subscribe()の問題のようでした。
デモで作ってるときなんて、頻繁にサーバ再起動すると思うのですが、それによってサーバの鍵が更新されるように作っていました。
subscribe()は登録されていたらそれを使うようになっているので、古いサーバ鍵でPush通知の処理を行おうとしていたので400エラーを吐いていたようです。
unsubscribe(),subscribe(),getSubscription()等を用いて、きちんと購読の更新もしてあげるようにしましょう。
商用で使いたい場合には
serviceWorkerにpushsubscriptionchangeイベントがあるのでこいつを上手く使って、更新を書けるようにすると良いらしいです。
終わりに
GoogleのProgressive Web appとかInstant Appsとか、そんなものを見ていると、Webに回帰する動きは今後強まりそうな気がします。
そうなるとPush通知も当然、必要になりそうな予感がします。
是非やってみてください、そしてできれば僕に教えてください。
ServiceWorkerのPushイベントのリスナーだけやりたい場合は、
デベロッパーツール(F12)のApplicationのServiceWorker使うとよいです、便利です。
※まだ、不特定多数に送るような処理は、やっていないので、やったらそこらへんやったらまた追記とかするかもしれません。