Convert all push recipes to use VAPID
This commit is contained in:
Родитель
896b9cc377
Коммит
fdf0806969
|
@ -11,8 +11,6 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to control the clients of a service worker when the user clicks on a push notification.</p>
|
||||
|
@ -26,6 +24,7 @@
|
|||
|
||||
<button id="doIt">Send notification</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
var endpoint;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -25,15 +31,23 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in real
|
||||
// applications the notification will be generated by some event on the server).
|
||||
document.getElementById('doIt').addEventListener('click', function() {
|
||||
fetch('./sendNotification?endpoint=' + endpoint, {
|
||||
method: 'post',
|
||||
});
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Clients - Service Worker Cookbook",
|
||||
"short_name": "push-clients",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,22 +2,40 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
const subscription = req.body.subscription;
|
||||
const payload = null;
|
||||
const options = {
|
||||
TTL: req.body.ttl
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.query.endpoint,
|
||||
TTL: req.query.ttl,
|
||||
})
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@ Send push notifications and retrieve a payload once a notification is received.
|
|||
Beginner
|
||||
|
||||
## Use Case
|
||||
This recipe demonstrates how you can deliver a notification and retrieve a payload when it arrives, also for browsers that don't currently support push messages with payload.
|
||||
This recipe demonstrates how you can deliver a notification and retrieve a payload when it arrives.
|
||||
|
||||
## Category
|
||||
Web Push
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to send push notifications and retrieve a payload when the notification is received.</p>
|
||||
|
@ -25,6 +23,7 @@ Notification Time-To-Live: <input id='notification-ttl' type='number' value='0'>
|
|||
|
||||
<button id="doIt">Request sending a notification!</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
var endpoint;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -25,29 +31,30 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
const payload = document.getElementById('notification-payload').value;
|
||||
const delay = document.getElementById('notification-delay').value;
|
||||
const ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
payload: payload,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
var payload = document.getElementById('notification-payload').value;
|
||||
var delay = document.getElementById('notification-delay').value;
|
||||
var ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: endpoint,
|
||||
payload: payload,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Payload - Service Worker Cookbook",
|
||||
"short_name": "push-get-payload",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,25 +2,43 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
var payloads = {};
|
||||
const payloads = {};
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
const subscription = req.body.subscription;
|
||||
const payload = req.body.payload;
|
||||
const options = {
|
||||
TTL: req.body.ttl
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
payloads[req.body.endpoint] = req.body.payload;
|
||||
webPush.sendNotification({
|
||||
endpoint: req.body.endpoint,
|
||||
TTL: req.body.ttl,
|
||||
})
|
||||
payloads[req.body.endpoint] = payload;
|
||||
webPush.sendNotification(subscription, null, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to send push notifications with a payload.</p>
|
||||
|
@ -25,6 +23,7 @@ Notification Time-To-Live: <input id='notification-ttl' type='number' value='0'>
|
|||
|
||||
<button id="doIt">Request sending a notification!</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,35 +1,29 @@
|
|||
var endpoint;
|
||||
var key;
|
||||
var authSecret;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
// Retrieve the user's public key.
|
||||
var rawKey = subscription.getKey ? subscription.getKey('p256dh') : '';
|
||||
key = rawKey ?
|
||||
btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) :
|
||||
'';
|
||||
var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : '';
|
||||
authSecret = rawAuthSecret ?
|
||||
btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) :
|
||||
'';
|
||||
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -37,33 +31,30 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
key: key,
|
||||
authSecret: authSecret,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
const payload = document.getElementById('notification-payload').value;
|
||||
const delay = document.getElementById('notification-delay').value;
|
||||
const ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
payload: payload,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
var payload = document.getElementById('notification-payload').value;
|
||||
var delay = document.getElementById('notification-delay').value;
|
||||
var ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: endpoint,
|
||||
key: key,
|
||||
authSecret: authSecret,
|
||||
payload: payload,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Payload - Service Worker Cookbook",
|
||||
"short_name": "push-payload",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,26 +2,40 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
const subscription = req.body.subscription;
|
||||
const payload = req.body.payload;
|
||||
const options = {
|
||||
TTL: req.body.ttl
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.body.endpoint,
|
||||
TTL: req.body.ttl,
|
||||
keys: {
|
||||
p256dh: req.body.key,
|
||||
auth: req.body.authSecret
|
||||
}
|
||||
}, req.body.payload)
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ self.addEventListener('push', function(event) {
|
|||
// Retrieve the textual payload from event.data (a PushMessageData object).
|
||||
// Other formats are supported (ArrayBuffer, Blob, JSON), check out the documentation
|
||||
// on https://developer.mozilla.org/en-US/docs/Web/API/PushMessageData.
|
||||
var payload = event.data ? event.data.text() : 'no payload';
|
||||
const payload = event.data ? event.data.text() : 'no payload';
|
||||
|
||||
// Keep the service worker alive until the notification is created.
|
||||
event.waitUntil(
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
color: red;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo allows you to experiment with the quota management rules enforced by browsers.
|
||||
|
@ -39,6 +37,7 @@ Number of notifications to send: <input id="notification-num" type="number" valu
|
|||
Received <span id="sent-invisible">0</span> invisible notifications</p>
|
||||
<button id="clear">Clear</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,36 +1,29 @@
|
|||
var endpoint;
|
||||
var key;
|
||||
var authSecret;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (unlike the other push recipes, here we don't set
|
||||
// the userVisibleOnly property because we don't plan to only send notifications that
|
||||
// have a visible effect for the user).
|
||||
return registration.pushManager.subscribe();
|
||||
return registration.pushManager.subscribe({
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
// Retrieve the user's public key.
|
||||
var rawKey = subscription.getKey ? subscription.getKey('p256dh') : '';
|
||||
key = rawKey ?
|
||||
btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) :
|
||||
'';
|
||||
var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : '';
|
||||
authSecret = rawAuthSecret ?
|
||||
btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) :
|
||||
'';
|
||||
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -38,65 +31,63 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
key: key,
|
||||
authSecret: authSecret,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
function askForNotifications(visible) {
|
||||
var notificationNum = document.getElementById('notification-num').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in real
|
||||
// applications the notification will be generated by some event on the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: endpoint,
|
||||
key: key,
|
||||
authSecret: authSecret,
|
||||
visible: visible,
|
||||
num: notificationNum,
|
||||
}),
|
||||
});
|
||||
}
|
||||
function askForNotifications(visible) {
|
||||
var notificationNum = document.getElementById('notification-num').value;
|
||||
|
||||
document.getElementById('visible').onclick = function() {
|
||||
// Ask the server to send a notification, that the service worker will then use
|
||||
// to show a visible notification.
|
||||
askForNotifications(true);
|
||||
};
|
||||
|
||||
document.getElementById('invisible').onclick = function() {
|
||||
// Ask the server to send a notification, that the service worker will not use
|
||||
// to show a visible notification.
|
||||
askForNotifications(false);
|
||||
};
|
||||
|
||||
document.getElementById('clear').onclick = function() {
|
||||
// Clear the 'notifications' cache, that stores the number of visible/invisible
|
||||
// notifications received.
|
||||
window.caches.open('notifications').then(function(cache) {
|
||||
Promise.all([
|
||||
cache.put(new Request('invisible'), new Response('0', {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
})),
|
||||
cache.put(new Request('visible'), new Response('0', {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
})),
|
||||
]).then(function() {
|
||||
updateNumbers();
|
||||
// Ask the server to send the client a notification (for testing purposes, in real
|
||||
// applications the notification will be generated by some event on the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
visible: visible,
|
||||
num: notificationNum,
|
||||
}),
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
document.getElementById('visible').onclick = function() {
|
||||
// Ask the server to send a notification, that the service worker will then use
|
||||
// to show a visible notification.
|
||||
askForNotifications(true);
|
||||
};
|
||||
|
||||
document.getElementById('invisible').onclick = function() {
|
||||
// Ask the server to send a notification, that the service worker will not use
|
||||
// to show a visible notification.
|
||||
askForNotifications(false);
|
||||
};
|
||||
|
||||
document.getElementById('clear').onclick = function() {
|
||||
// Clear the 'notifications' cache, that stores the number of visible/invisible
|
||||
// notifications received.
|
||||
window.caches.open('notifications').then(function(cache) {
|
||||
Promise.all([
|
||||
cache.put(new Request('invisible'), new Response('0', {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
})),
|
||||
cache.put(new Request('visible'), new Response('0', {
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
})),
|
||||
]).then(function() {
|
||||
updateNumbers();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
function updateNumbers() {
|
||||
// Read the number of notifications received from the 'notifications' cache and
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Quota - Service Worker Cookbook",
|
||||
"short_name": "push-quota",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,11 +2,26 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
|
@ -17,19 +32,18 @@ module.exports = function(app, route) {
|
|||
// - 'true': show a notification;
|
||||
// - 'false': don't show a notification.
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
var num = 1;
|
||||
const subscription = req.body.subscription;
|
||||
const payload = null;
|
||||
const options = {
|
||||
TTL: 200
|
||||
};
|
||||
|
||||
var promises = [];
|
||||
let num = 1;
|
||||
|
||||
var intervalID = setInterval(function() {
|
||||
promises.push(webPush.sendNotification({
|
||||
endpoint: req.body.endpoint,
|
||||
TTL: 200,
|
||||
keys: {
|
||||
p256dh: req.body.key,
|
||||
auth: req.body.authSecret,
|
||||
}
|
||||
}));
|
||||
let promises = [];
|
||||
|
||||
let intervalID = setInterval(function() {
|
||||
promises.push(webPush.sendNotification(subscription, payload, options));
|
||||
|
||||
if (num++ === Number(req.body.num)) {
|
||||
clearInterval(intervalID);
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to replace an old notification with a new one.</p>
|
||||
|
@ -23,6 +21,7 @@ Delay between notifications: <input id='notification-delay' type='number' value=
|
|||
|
||||
<button id="doIt">Request notifications</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
var endpoint;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -25,20 +31,26 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
var notificationDelay = document.getElementById('notification-delay').value;
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
const delay = document.getElementById('notification-delay').value;
|
||||
|
||||
// Ask the server to send the client a few notifications (for testing purposes, in real
|
||||
// applications notifications will be generated by events on the server).
|
||||
fetch('./sendNotification?endpoint=' + endpoint +
|
||||
'&delay=' + notificationDelay,
|
||||
{
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
}
|
||||
);
|
||||
};
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
delay: delay,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Replace - Service Worker Cookbook",
|
||||
"short_name": "push-replace",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,33 +2,48 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.query.endpoint,
|
||||
TTL: 200,
|
||||
})
|
||||
const subscription = req.body.subscription;
|
||||
const payload = null;
|
||||
const options = {
|
||||
TTL: 200
|
||||
};
|
||||
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.catch(logError);
|
||||
|
||||
setTimeout(function() {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.query.endpoint,
|
||||
TTL: 200,
|
||||
})
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
.catch(logError);
|
||||
}, req.query.delay * 1000);
|
||||
}, req.body.delay * 1000);
|
||||
|
||||
function logError(error) {
|
||||
res.sendStatus(500);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var num = 1;
|
||||
let num = 1;
|
||||
|
||||
// Register event listener for the 'push' event.
|
||||
self.addEventListener('push', function(event) {
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to show rich push notifications.</p>
|
||||
|
@ -24,6 +22,7 @@ Notification Time-To-Live: <input id='notification-ttl' type='number' value='0'>
|
|||
|
||||
<button id="doIt">Try to conquer Italy!</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
var endpoint;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -25,21 +31,28 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
var delay = document.getElementById('notification-delay').value;
|
||||
var ttl = document.getElementById('notification-ttl').value;
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
const delay = document.getElementById('notification-delay').value;
|
||||
const ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification (for testing purposes, in real
|
||||
// applications the notification will be generated by some event on the server).
|
||||
fetch('./sendNotification?endpoint=' + endpoint + '&delay=' + delay +
|
||||
'&ttl=' + ttl,
|
||||
{
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
}
|
||||
);
|
||||
};
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Rich - Service Worker Cookbook",
|
||||
"short_name": "push-rich",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,29 +2,47 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
const subscription = req.body.subscription;
|
||||
const payload = null;
|
||||
const options = {
|
||||
TTL: req.body.ttl
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.query.endpoint,
|
||||
TTL: req.query.ttl,
|
||||
})
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
.catch(function(error) {
|
||||
res.sendStatus(500);
|
||||
console.log(error);
|
||||
})
|
||||
}, req.query.delay * 1000);
|
||||
res.sendStatus(500);
|
||||
});
|
||||
}, req.body.delay * 1000);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -10,13 +10,7 @@
|
|||
font-size: 1rem;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
span {
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<p>This demo shows how to register for push notifications and how to send them.</p>
|
||||
|
@ -26,12 +20,9 @@ Notification delay: <input id='notification-delay' type='number' value='5'></inp
|
|||
Notification Time-To-Live: <input id='notification-ttl' type='number' value='0'></input> seconds
|
||||
</form>
|
||||
|
||||
<p>Either click this button to ask the server to send a notification: <button id="doIt">Try to conquer Italy!</button></p>
|
||||
<p>Or use <b>curl</b> on your command line to send the notification:</p>
|
||||
<span id="curl"></span>
|
||||
|
||||
<p>N.B.: The curl command only works for push services implementing the Web Push standard (GCM, the push service used by Google Chrome, currently doesn't).</p>
|
||||
<button id="doIt">Try to conquer Italy!</button>
|
||||
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
var endpoint;
|
||||
|
||||
// Register a Service Worker.
|
||||
navigator.serviceWorker.register('service-worker.js')
|
||||
.then(function(registration) {
|
||||
// Use the PushManager to get the user's subscription to the push service.
|
||||
return registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
.then(async function(subscription) {
|
||||
// If a subscription was found, return it.
|
||||
if (subscription) {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
|
||||
// Otherwise, subscribe the user (userVisibleOnly allows to specify that we don't plan to
|
||||
// send notifications that don't have a visible effect for the user).
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
endpoint = subscription.endpoint;
|
||||
|
||||
// Show curl command to send the notification on the page.
|
||||
document.getElementById('curl').textContent = 'curl -H "TTL: 60" -X POST ' + endpoint;
|
||||
|
||||
// Send the subscription details to the server using the Fetch API.
|
||||
fetch('./register', {
|
||||
method: 'post',
|
||||
|
@ -28,23 +31,28 @@ navigator.serviceWorker.register('service-worker.js')
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint,
|
||||
subscription: subscription
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
var delay = document.getElementById('notification-delay').value;
|
||||
var ttl = document.getElementById('notification-ttl').value;
|
||||
document.getElementById('doIt').onclick = function() {
|
||||
const delay = document.getElementById('notification-delay').value;
|
||||
const ttl = document.getElementById('notification-ttl').value;
|
||||
|
||||
// Ask the server to send the client a notification.
|
||||
// This is for testing purposes, in a real application the notifications will be
|
||||
// directly generated by the server without the user asking for it (otherwise, what
|
||||
// would be the point?).
|
||||
fetch('./sendNotification?endpoint=' + endpoint + '&delay=' + delay +
|
||||
'&ttl=' + ttl,
|
||||
{
|
||||
// Ask the server to send the client a notification (for testing purposes, in actual
|
||||
// applications the push notification is likely going to be generated by some event
|
||||
// in the server).
|
||||
fetch('./sendNotification', {
|
||||
method: 'post',
|
||||
}
|
||||
);
|
||||
};
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: subscription,
|
||||
delay: delay,
|
||||
ttl: ttl,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "Push Simple - Service Worker Cookbook",
|
||||
"short_name": "push-simple",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -2,22 +2,40 @@
|
|||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
var webPush = require('web-push');
|
||||
const webPush = require('web-push');
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
module.exports = function(app, route) {
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
app.post(route + 'register', function(req, res) {
|
||||
// A real world application would store the subscription info.
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
app.post(route + 'sendNotification', function(req, res) {
|
||||
const subscription = req.body.subscription;
|
||||
const payload = null;
|
||||
const options = {
|
||||
TTL: req.body.ttl
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
webPush.sendNotification({
|
||||
endpoint: req.query.endpoint,
|
||||
TTL: req.query.ttl,
|
||||
})
|
||||
webPush.sendNotification(subscription, payload, options)
|
||||
.then(function() {
|
||||
res.sendStatus(201);
|
||||
})
|
||||
|
@ -25,6 +43,6 @@ module.exports = function(app, route) {
|
|||
res.sendStatus(500);
|
||||
console.log(error);
|
||||
});
|
||||
}, req.query.delay * 1000);
|
||||
}, req.body.delay * 1000);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,14 +11,12 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<!-- This is needed for Google Chrome support. -->
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>This demo shows how to subscribe/unsubscribe to the push notifications.</p>
|
||||
<button id='subscriptionButton' disabled=true></button>
|
||||
<p>To simulate the subscription expiration under Firefox please set the <code>dom.push.userAgentId</code> in about:config to an empty string. (Note: <A href="https://bugzilla.mozilla.org/show_bug.cgi?id=1222428">bug 1222428</a>)</p>
|
||||
<script src='./index.js'></script>
|
||||
<script src="/tools.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -32,11 +32,21 @@ if ('serviceWorker' in navigator) {
|
|||
|
||||
// Get the `registration` from service worker and create a new
|
||||
// subscription using `registration.pushManager.subscribe`. Then
|
||||
// register received new subscription by sending a POST request with its
|
||||
// endpoint to the server.
|
||||
// register received new subscription by sending a POST request with
|
||||
// the subscription to the server.
|
||||
function subscribe() {
|
||||
navigator.serviceWorker.ready.then(function(registration) {
|
||||
return registration.pushManager.subscribe({ userVisibleOnly: true });
|
||||
navigator.serviceWorker.ready.then(async function(registration) {
|
||||
// Get the server's public key
|
||||
const response = await fetch('./vapidPublicKey');
|
||||
const vapidPublicKey = await response.text();
|
||||
// Chrome doesn't accept the base64-encoded (string) vapidPublicKey yet
|
||||
// urlBase64ToUint8Array() is defined in /tools.js
|
||||
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
|
||||
// Subscribe the user
|
||||
return registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: convertedVapidKey
|
||||
});
|
||||
}).then(function(subscription) {
|
||||
console.log('Subscribed', subscription.endpoint);
|
||||
return fetch('register', {
|
||||
|
@ -45,7 +55,7 @@ function subscribe() {
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint
|
||||
subscription: subscription
|
||||
})
|
||||
});
|
||||
}).then(setUnsubscribeButton);
|
||||
|
@ -66,7 +76,7 @@ function unsubscribe() {
|
|||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: subscription.endpoint
|
||||
subscription: subscription
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "RECIPE: Push notifications with subscription management",
|
||||
"short_name": "recipe_push_with_subscription",
|
||||
"start_url": "/index.html",
|
||||
"display": "standalone",
|
||||
"gcm_sender_id": "829371921996",
|
||||
"gcm_user_visible_only": true
|
||||
}
|
|
@ -1,29 +1,42 @@
|
|||
// [Working example](/serviceworker-cookbook/push-subscription-management/).
|
||||
|
||||
// `web-push` is a library which makes sending notifications a very
|
||||
// simple process.
|
||||
var webPush = require('web-push');
|
||||
// Use the web-push library to hide the implementation details of the communication
|
||||
// between the application server and the push service.
|
||||
// For details, see https://tools.ietf.org/html/draft-ietf-webpush-protocol and
|
||||
// https://tools.ietf.org/html/draft-ietf-webpush-encryption.
|
||||
const webPush = require('web-push');
|
||||
|
||||
if (!process.env.VAPID_PUBLIC_KEY || !process.env.VAPID_PRIVATE_KEY) {
|
||||
console.log("You must set the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY "+
|
||||
"environment variables. You can use the following ones:");
|
||||
console.log(webPush.generateVAPIDKeys());
|
||||
return;
|
||||
}
|
||||
// Set the keys used for encrypting the push messages.
|
||||
webPush.setVapidDetails(
|
||||
'https://serviceworke.rs/',
|
||||
process.env.VAPID_PUBLIC_KEY,
|
||||
process.env.VAPID_PRIVATE_KEY,
|
||||
);
|
||||
|
||||
// Global array collecting all active endpoints. In real world
|
||||
// application one would use a database here.
|
||||
var subscriptions = [];
|
||||
const subscriptions = {};
|
||||
|
||||
// How often (in seconds) should the server send a notification to the
|
||||
// user.
|
||||
var pushInterval = 10;
|
||||
const pushInterval = 10;
|
||||
|
||||
webPush.setGCMAPIKey(process.env.GCM_API_KEY || null);
|
||||
|
||||
// Send notification to the push service. Remove the endpoint from the
|
||||
// Send notification to the push service. Remove the subscription from the
|
||||
// `subscriptions` array if the push service responds with an error.
|
||||
// Subscription has been cancelled or expired.
|
||||
function sendNotification(endpoint) {
|
||||
webPush.sendNotification({
|
||||
endpoint: endpoint
|
||||
}).then(function() {
|
||||
console.log('Push Application Server - Notification sent to ' + endpoint);
|
||||
function sendNotification(subscription) {
|
||||
webPush.sendNotification(subscription)
|
||||
.then(function() {
|
||||
console.log('Push Application Server - Notification sent to ' + subscription.endpoint);
|
||||
}).catch(function() {
|
||||
console.log('ERROR in sending Notification, endpoint removed ' + endpoint);
|
||||
subscriptions.splice(subscriptions.indexOf(endpoint), 1);
|
||||
console.log('ERROR in sending Notification, endpoint removed ' + subscription.endpoint);
|
||||
delete subscriptions[subscription.endpoint];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,31 +44,30 @@ function sendNotification(endpoint) {
|
|||
// To simulate it, server is sending a notification every `pushInterval` seconds
|
||||
// to each registered endpoint.
|
||||
setInterval(function() {
|
||||
subscriptions.forEach(sendNotification);
|
||||
Object.values(subscriptions).forEach(sendNotification);
|
||||
}, pushInterval * 1000);
|
||||
|
||||
function isSubscribed(endpoint) {
|
||||
return (subscriptions.indexOf(endpoint) >= 0);
|
||||
}
|
||||
|
||||
module.exports = function(app, route) {
|
||||
// Register a subscription by adding an endpoint to the `subscriptions`
|
||||
// array.
|
||||
app.get(route + 'vapidPublicKey', function(req, res) {
|
||||
res.send(process.env.VAPID_PUBLIC_KEY);
|
||||
});
|
||||
|
||||
// Register a subscription by adding it to the `subscriptions` array.
|
||||
app.post(route + 'register', function(req, res) {
|
||||
var endpoint = req.body.endpoint;
|
||||
if (!isSubscribed(endpoint)) {
|
||||
console.log('Subscription registered ' + endpoint);
|
||||
subscriptions.push(endpoint);
|
||||
var subscription = req.body.subscription;
|
||||
if (!subscriptions[subscription.endpoint]) {
|
||||
console.log('Subscription registered ' + subscription.endpoint);
|
||||
subscriptions[subscription.endpoint] = subscription;
|
||||
}
|
||||
res.type('js').send('{"success":true}');
|
||||
});
|
||||
|
||||
// Unregister a subscription by removing it from the `subscriptions` array
|
||||
app.post(route + 'unregister', function(req, res) {
|
||||
var endpoint = req.body.endpoint;
|
||||
if (isSubscribed(endpoint)) {
|
||||
console.log('Subscription unregistered ' + endpoint);
|
||||
subscriptions.splice(subscriptions.indexOf(endpoint), 1);
|
||||
var subscription = req.body.subscription;
|
||||
if (subscriptions[subscription.endpoint]) {
|
||||
console.log('Subscription unregistered ' + subscription.endpoint);
|
||||
delete subscriptions[subscription.endpoint];
|
||||
}
|
||||
res.type('js').send('{"success":true}');
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче