【PWA】シリーズPWA (10) クライアントからAPIにリクエストを送って通知を受け取る
クライアント側の実装
クライアント側は、基本的に前回までで実装したAPIを叩きにいくように変更します。
サブスクリプション の登録(と古いものがあれば削除)
前回の実装では、サブスクリプションの情報をconsoleに出力するだけでしたが、実際にサブスクリプションの情報をリクエストヘッダーに乗せてAPIを叩きます。
まずmain.jsにおいてこのようになっていた箇所を、
navigator.serviceWorker.ready.then(function(registration) { return registration.pushManager.getSubscription().then(function(subscription) { if (subscription) return subscription; return registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: convertedVapidKey }).then(function (subscription) { var rawKey = subscription.getKey ? subscription.getKey('p256dh') : ''; var key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ''; var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : ''; var auth = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : ''; var endpoint = subscription.endpoint; console.log(key); console.log(auth); console.log(endpoint); }); }) });
このように書き換えます。
var sendSubscription = function(subscription){ var data = {}; var latestID = localStorage.getItem('latestID'); var rawKey = subscription.getKey ? subscription.getKey('p256dh') : ''; data.key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ''; var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : ''; data.auth = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : ''; data.endpoint = subscription.endpoint; data.registrationID = data.endpoint.substring(data.endpoint.lastIndexOf('/')+1, data.endpoint.length); localStorage.setItem('latestID', data.registrationID); // 新しいサブスクリプションを通知対象に登録する fetch('https://*******/add',{ method: 'POST', headers: { 'Content-Type': 'application/json' }, mode: 'cors', body: JSON.stringify(data) }) .then(function(response) { return response.text(); }) .then(function(res){ console.log(res); }); // 古いサブスクリプションがあれば通知対象から削除する if (latestID) { fetch('https://*******/delete',{ method: 'POST', headers: { 'Content-Type': 'application/json' }, mode: 'cors', body: JSON.stringify({ registrationID: latestID}) }) .then(function(response) { return response.text(); }) .then(function(res){ console.log(res); }); } } navigator.serviceWorker.ready.then(function(registration) { return registration.pushManager.getSubscription().then(function(subscription) { if (subscription) return subscription; return registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: convertedVapidKey }).then(function (subscription) { sendSubscription(subscription); }); }) });
サブスクリプションの情報をJSON形式にしてリクエストヘッダーに持たせています。
また、最新のregistrationIDを常にlocalStorageで管理し、古いものがあれば(つまりlocalStorageに格納されたregistrationIDがあれば)そのIDは削除するようAPIを叩いています。
push用ページを作成する
pushについては任意の通知内容を設定できるように専用のフォームページを作成し、そのフォームがsubmitされたタイミングで、pushするためのAPIを叩きに行くようにします。 仮にファイル名をpush.htmlとします。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <form method="POST" id="form"> Title <input type="text" name="title"> Message <input type="text" name="message"> <button type="submit">Push</button> </form> <script> document.querySelector('#form').addEventListener('submit', function(e){ e.preventDefault(); var title = document.querySelector('#form').querySelector('[name="title"]').value; var message = document.querySelector('#form').querySelector('[name="message"]').value; var data = { title: title, message: message }; fetch('https://******/push',{ method: 'POST', headers: { 'Content-Type': 'application/json' }, mode: 'cors', body: JSON.stringify(data) }) .then(function(response) { return response.text(); }) .then(function(res){ console.log(res) }) }, false) </script> </body> </html>
push.htmlにアクセスし、テキストフィールドに任意の値を入力してボタンを押せば、入力した内容で通知が送られてくるはずです。