Envoyer des messages à l'aide de bibliothèques Web Push

Lorsque vous utilisez la fonctionnalité Web push, le déclenchement d'un message push est extrêmement avec attention. Pour déclencher un message push, une application doit envoyer une requête POST à un type après l'envoi du Web push protocole. Pour utiliser la fonctionnalité Push sur navigateurs, vous devez utiliser VAPID (clés de serveur d'applications), ce qui nécessite essentiellement de définir un en-tête avec une valeur prouvant votre application peut envoyer un message à un utilisateur. Pour envoyer des données avec un message push, elles doivent être en-têtes chiffrés et spécifiques doivent être ajoutées pour que le navigateur puisse déchiffrer correctement le message.

Le principal problème lié au déclenchement du mode push est que, si un problème survient, le problème. Cela s'améliore avec le temps et avec une prise en charge plus large des navigateurs, mais c'est loin d'être facile. Pour c'est pourquoi je vous recommande vivement d'utiliser une bibliothèque pour gérer le chiffrement, le formatage et le déclenchement de votre message push.

Si vous voulez vraiment en savoir plus sur le fonctionnement des bibliothèques, nous y aborderons dans la section suivante. Pour l'instant, nous allons nous intéresser à la gestion des abonnements et à l'utilisation d'un la bibliothèque Web push existante pour effectuer les requêtes push.

Dans cette section, nous allons utiliser le nœud web-push bibliothèque. D'autres langues auront des différences, mais ils ne seront pas trop différents. Nous examinons Node.js, car il s'agit de JavaScript et il devrait s'agir les plus accessibles pour les lecteurs.

Voici les étapes à suivre:

  1. Envoyez un abonnement à notre backend et enregistrez-le.
  2. Récupérez les abonnements enregistrés et déclenchez un message push.

Enregistrement des abonnements...

L'enregistrement et l'interrogation des PushSubscription à partir d'une base de données varient en fonction de votre langage côté serveur et votre choix de base de données, mais il peut être utile un exemple de la façon dont cela pourrait être fait.

Sur la page Web de démonstration, le PushSubscription est envoyé à notre backend via une simple requête POST:

function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(subscription),
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('Bad status code from server.');
      }

      return response.json();
    })
    .then(function (responseData) {
      if (!(responseData.data && responseData.data.success)) {
        throw new Error('Bad response from server.');
      }
    });
}

Dans notre démonstration, le serveur Express possède un écouteur de requêtes correspondant pour la fonction Point de terminaison /api/save-subscription/:

app.post('/api/save-subscription/', function (req, res) {

Dans ce cas, nous validons l'abonnement juste pour nous assurer que la demande est correcte et qu'elle n'est pas remplie de ordure:

const isValidSaveRequest = (req, res) => {
  // Check the request body has at least an endpoint.
  if (!req.body || !req.body.endpoint) {
    // Not a valid subscription.
    res.status(400);
    res.setHeader('Content-Type', 'application/json');
    res.send(
      JSON.stringify({
        error: {
          id: 'no-endpoint',
          message: 'Subscription must have an endpoint.',
        },
      }),
    );
    return false;
  }
  return true;
};

Si l'abonnement est valide, nous devons l'enregistrer et renvoyer un Réponse JSON:

return saveSubscriptionToDatabase(req.body)
  .then(function (subscriptionId) {
    res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({data: {success: true}}));
  })
  .catch(function (err) {
    res.status(500);
    res.setHeader('Content-Type', 'application/json');
    res.send(
      JSON.stringify({
        error: {
          id: 'unable-to-save-subscription',
          message:
            'The subscription was received but we were unable to save it to our database.',
        },
      }),
    );
  });

Cette démonstration utilise nedb pour stocker les abonnements. simple basée sur des fichiers, mais vous pouvez utiliser n'importe quelle base de données de votre choix. Nous l'utilisons uniquement il ne nécessite aucune configuration. Pour la production, vous devez utiliser quelque chose de plus fiable. (J'ai tendance à tenez-vous-en à la bonne vieille MySQL.)

function saveSubscriptionToDatabase(subscription) {
  return new Promise(function (resolve, reject) {
    db.insert(subscription, function (err, newDoc) {
      if (err) {
        reject(err);
        return;
      }

      resolve(newDoc._id);
    });
  });
}

Envoyer des messages push

Lorsqu'il s'agit d'envoyer un message push, nous avons au final besoin d'un événement pour déclencher le processus de l'envoi d'un message aux utilisateurs. Une approche courante consiste à créer une page d'administration qui vous permet configurer et déclencher le message push. Mais vous pouvez créer un programme à exécuter en local ou n'importe quelle Autre approche permettant d'accéder à la liste des PushSubscription et d'exécuter le code pour pour déclencher le message push.

Dans notre démonstration, nous avons une vision d'administration qui vous permet de déclencher un transfert. Comme il ne s'agit que d'une démonstration, page publique.

Je vais passer en revue chaque étape nécessaire au fonctionnement de la démonstration. Ce sont des bébés pour que tout le monde puisse suivre, y compris toute personne qui débute sur Node.

Lorsque nous avons abordé l'abonnement d'un utilisateur, nous avons vu l'ajout d'un applicationServerKey au Options subscribe(). C'est sur le backend que nous aurons besoin de cette clé privée.

Dans la démonstration, ces valeurs sont ajoutées à notre application Node comme ceci (code ennuyeux que je connais, vous savez qu'il n'y a pas de magie):

const vapidKeys = {
  publicKey:
    'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
  privateKey: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls',
};

Nous devons ensuite installer le module web-push pour notre serveur de nœuds:

npm install web-push --save

Ensuite, dans notre script Node, nous avons besoin du module web-push. comme suit:

const webpush = require('web-push');

Nous pouvons maintenant commencer à utiliser le module web-push. Vous devez d'abord indiquer au module web-push nos clés de serveur d'applications. (N'oubliez pas qu'elles sont aussi appelées clés VAPID, car il s'agit du nom de la spécification.)

const vapidKeys = {
  publicKey:
    'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
  privateKey: 'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls',
};

webpush.setVapidDetails(
  'mailto:web-push-book@gauntface.com',
  vapidKeys.publicKey,
  vapidKeys.privateKey,
);

Notez que nous avons également inclus un . Cette chaîne doit être une URL ou un adresse e-mail. Cette information est envoyée au service Web push la requête pour déclencher un transfert. En effet, si un service Web push a besoin contacter l'expéditeur, il dispose de certaines informations qui lui permettront de le faire.

Le module web-push est maintenant prêt à l'emploi. L'étape suivante consiste à déclencher un message push.

La démonstration utilise le panneau d'administration fictif pour déclencher l'envoi de messages push.

Capture d'écran de la page d'administration.

En cliquant sur "Trigger Push Message" (Déclencher un message push), enverra une requête POST à /api/trigger-push-msg/, qui est le signal pour que notre backend envoie des messages push. Nous créons donc la route dans express pour ce point de terminaison:

app.post('/api/trigger-push-msg/', function (req, res) {

À réception de cette demande, nous récupérons les abonnements dans la base de données et pour chacun d'eux, nous déclenchons un message push.

return getSubscriptionsFromDatabase().then(function (subscriptions) {
  let promiseChain = Promise.resolve();

  for (let i = 0; i < subscriptions.length; i++) {
    const subscription = subscriptions[i];
    promiseChain = promiseChain.then(() => {
      return triggerPushMsg(subscription, dataToSend);
    });
  }

  return promiseChain;
});

La fonction triggerPushMsg() peut ensuite utiliser la bibliothèque web-push pour envoyer un message au un abonnement fourni.

const triggerPushMsg = function (subscription, dataToSend) {
  return webpush.sendNotification(subscription, dataToSend).catch((err) => {
    if (err.statusCode === 404 || err.statusCode === 410) {
      console.log('Subscription has expired or is no longer valid: ', err);
      return deleteSubscriptionFromDatabase(subscription._id);
    } else {
      throw err;
    }
  });
};

L'appel à webpush.sendNotification() renvoie une promesse. Si le a bien été envoyé, la promesse est résolue et il y a nous n'avons rien à faire. Si la promesse est refusée, vous devez examiner le car elle vous indique si PushSubscription est toujours valides ou non.

Pour déterminer le type d'erreur d'un service push, il est préférable d'examiner le code d'état. Erreur les messages varient selon les services push et certains sont plus utiles que d'autres.

Dans cet exemple, elle recherche les codes d'état 404 et 410, qui sont les codes d'état HTTP de Introuvable et « Supprimé ». Si nous recevons l'un de ces messages, cela signifie que l'abonnement a expiré. ou n'est plus valide. Dans ce cas, nous devons supprimer les abonnements de notre base de données.

En cas d'autre erreur, il suffit d'utiliser throw err, ce qui rend la promesse renvoyée par triggerPushMsg() refus.

Nous aborderons d'autres codes d'état dans la section suivante, qui concerne l'authentification Web push protocole de configuration.

Après avoir parcouru les abonnements en boucle, nous devons renvoyer une réponse JSON.

.then(() => {
res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({ data: { success: true } }));
})
.catch(function(err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({
    error: {
    id: 'unable-to-send-messages',
    message: `We were unable to send messages to all subscriptions : ` +
        `'${err.message}'`
    }
}));
});

Nous avons passé en revue les principales étapes d'implémentation:

  1. Créer une API pour envoyer les abonnements de notre page Web vers notre backend afin de pouvoir les enregistrer dans une base de données.
  2. Créez une API pour déclencher l'envoi de messages push (dans le cas présent, API appelée à partir du panneau d'administration fictif).
  3. Récupérer tous les abonnements depuis notre backend et envoyez un message à chaque abonnement via l'une des méthodes web-push bibliothèques.

Quel que soit votre backend (Node, PHP, Python, etc.), les étapes de mise en œuvre de la transmission qu'elles soient identiques.

À présent, que font exactement ces bibliothèques web-push pour nous ?

Étapes suivantes

Ateliers de programmation