S'abonner à un utilisateur

La première étape consiste à demander à l'utilisateur l'autorisation de lui envoyer des messages push. mettre la main sur un PushSubscription.

Pour ce faire, l'API JavaScript est relativement simple. tout au long du flux logique.

Détection de caractéristiques

Nous devons d'abord vérifier si le navigateur actuel prend en charge les messages push. Nous pouvons vérifier si la méthode push est compatible avec deux vérifications simples.

  1. Recherchez serviceWorker sur navigator.
  2. Recherchez PushManager dans window.
if (!('serviceWorker' in navigator)) {
  // Service Worker isn't supported on this browser, disable or hide UI.
  return;
}

if (!('PushManager' in window)) {
  // Push isn't supported on this browser, disable or hide UI.
  return;
}

Les navigateurs sont de plus en plus pris en charge, tant pour les service workers que pour les messages push, il est toujours judicieux de détecter les caractéristiques à la fois progressivement.

Enregistrer un service worker

Grâce à la détection de la fonctionnalité, nous savons que les service workers et le mode Push sont pris en charge. Étape suivante est d'« enregistrer » notre service worker.

Lorsque nous enregistrons un service worker, nous indiquons au navigateur l'emplacement de notre fichier. Il s'agit toujours d'un fichier JavaScript, mais le navigateur lui accorde l'accès au service worker telles que les API push. Pour être plus précis, le navigateur exécute le fichier dans un service worker. environnement.

Pour enregistrer un service worker, appelez navigator.serviceWorker.register() en transmettant le chemin d'accès à notre fichier. Comme ceci:

function registerServiceWorker() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function (err) {
      console.error('Unable to register service worker.', err);
    });
}

Cette fonction indique au navigateur que nous disposons d'un fichier service worker et indique son emplacement. Dans le fichier de service worker se trouve à l'emplacement /service-worker.js. Dans les coulisses du navigateur procède comme suit après avoir appelé register():

  1. Téléchargez le fichier service worker.

  2. Exécutez le code JavaScript.

  3. Si tout s'exécute correctement et qu'il n'y a pas d'erreur, la promesse renvoyée par register() est résolu. En cas d'erreur, quelle qu'elle soit, la promesse sera rejetée.

Si register() refuse, vérifiez que votre code JavaScript ne contient pas de fautes de frappe ni d'erreurs dans les outils pour les développeurs Chrome.

Lorsque register() est résolu, une exception ServiceWorkerRegistration est renvoyée. Nous l'utiliserons pour accéder à l'API PushManager.

Compatibilité du navigateur avec l'API PushManager

Navigateurs pris en charge

  • Chrome: 42 <ph type="x-smartling-placeholder">
  • Edge: 17 <ph type="x-smartling-placeholder">
  • Firefox: 44 <ph type="x-smartling-placeholder">
  • Safari: 16. <ph type="x-smartling-placeholder">

Source

Demande d'autorisation...

Notre service worker a été enregistré et nous sommes prêts à abonner l'utilisateur. L'étape suivante consiste à récupérer l'autorisation de l'utilisateur de lui envoyer des messages push.

L'API permettant d'obtenir des autorisations est relativement simple. L'API est récemment passée d'un rappel à renvoyer une promesse. La est que nous ne pouvons pas déterminer la version de l'API implémentée par la version actuelle navigateur. Vous devez donc implémenter les deux et les gérer.

function askPermission() {
  return new Promise(function (resolve, reject) {
    const permissionResult = Notification.requestPermission(function (result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  }).then(function (permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error("We weren't granted permission.");
    }
  });
}

Dans le code ci-dessus, l'extrait de code important est l'appel Notification.requestPermission() Cette méthode affiche une invite pour l'utilisateur:

Invite d&#39;autorisation sur ordinateur et mobile dans Chrome.

Une fois que l'utilisateur a interagi avec l'invite d'autorisation en appuyant sur "Autoriser", "Bloquer" ou en la fermant, Le résultat s'affiche sous forme de chaîne: 'granted', 'default' ou 'denied'.

Dans l'exemple de code ci-dessus, la promesse renvoyée par askPermission() résout si l'autorisation est accordé. Sinon, nous générons une erreur qui entraîne le rejet de la promesse.

Vous devez gérer un cas particulier si l'utilisateur clique sur le bouton . Si cette cela se produit, votre application Web ne pourra plus demander l'autorisation à l'utilisateur. Ils devront "débloquer" manuellement votre application en modifiant son état d'autorisation, qui est caché dans un panneau de paramètres. Réfléchissez bien à la façon et au moment où vous demandez l'autorisation à l'utilisateur, car s'ils cliquent sur "Bloquer", il n'est pas facile d'annuler cette décision.

La bonne nouvelle est que la plupart des utilisateurs sont heureux de donner leur autorisation tant que il sait pourquoi l'autorisation est demandée.

Nous verrons plus tard comment certains sites populaires demandent l'autorisation.

Abonner un utilisateur avec PushManager

Une fois notre service worker enregistré et l'autorisation obtenue, nous pouvons abonner un utilisateur en Appel de registration.pushManager.subscribe() en cours.

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

Lors de l'appel de la méthode subscribe(), nous transmettons un objet options, qui se compose à la fois les paramètres obligatoires et facultatifs.

Examinons toutes les options que nous pouvons transmettre.

Options userVisibleOnly

Lorsque la technologie push a été ajoutée pour la première fois aux navigateurs, il n'était pas certain que les développeurs en mesure d'envoyer un message push et de ne pas afficher de notification. Ceci est communément appelé silencieux car l'utilisateur ne savait pas qu'un événement s'était passé en arrière-plan.

Le problème était que les développeurs puissent faire des choses désagréables, comme suivre la position d'un utilisateur sur un sans que l'utilisateur s'en aperçoive.

Pour éviter ce scénario et laisser aux auteurs de spécifications le temps de réfléchir à la meilleure façon d'y parvenir , l'option userVisibleOnly a été ajoutée et la transmission de la valeur true est symbolique vous vous êtes mis d'accord avec le navigateur : l'application Web affiche une notification à chaque fois (pas de transmission silencieuse).

Pour le moment, vous devez transmettre la valeur true. Si vous n'incluez pas le paramètre userVisibleOnly ou transmettez false, vous obtenez l'erreur suivante:

Pour le moment, Chrome n'est compatible qu'avec l'API Push pour les abonnements qui entraînent messages visibles par les utilisateurs. Vous pouvez l'indiquer en appelant pushManager.subscribe({userVisibleOnly: true}) à la place. Voir https://goo.gl/yqv4Q4 pour en savoir plus.

On dirait que la notification push silencieuse globale ne sera jamais implémentée dans Chrome. À la place, les auteurs de spécifications explorent le concept d'API budgétaire qui permettra aux applications Web d'atteindre nombre de messages push silencieux en fonction de l'utilisation d'une application Web.

Option applicationServerKey

Nous avons brièvement mentionné les "clés de serveur d'applications". dans la section précédente. "Application "Clés de serveur" sont utilisés par un service push pour identifier l'application qui abonne un utilisateur pour s'assurer que la même application envoie des messages à cet utilisateur.

Les clés de serveur d'applications sont une paire de clés publique et privée propre à votre application. La clé privée doit rester secrète pour votre application et la clé publique peut être partagée en toute liberté.

L'option applicationServerKey transmise dans l'appel subscribe() est l'option publique de l'application . Le navigateur transmet cette information à un service push lors de l'abonnement de l'utilisateur. peut lier la clé publique de votre application au PushSubscription de l'utilisateur.

Le schéma ci-dessous illustre ces étapes.

  1. Votre application Web est chargée dans un navigateur et vous appelez subscribe() en transmettant votre la clé du serveur d'applications.
  2. Le navigateur envoie ensuite une requête réseau à un service push qui va générer un point de terminaison, associer ce point de terminaison à la clé publique de l'application et renvoyer le point de terminaison au navigateur.
  3. Le navigateur ajoutera ce point de terminaison à PushSubscription, qui est renvoyé via la subscribe().

Illustration de la clé publique du serveur d&#39;application utilisée dans &quot;S&#39;abonner&quot;
.

Par la suite, si vous souhaitez envoyer un message push, vous devez créer un en-tête Authorization qui contiendra les informations signées avec la clé privée de votre serveur d'applications. Lorsque reçoit une demande d'envoi d'un message push, il peut valider cet en-tête Authorization signé en recherchant la clé publique liée au point de terminaison qui reçoit la requête. Si la signature est si valide, le service push sait qu'il doit provenir du serveur d'applications avec le paramètre clé privée correspondante. C'est essentiellement une mesure de sécurité qui empêche toute autre personne d'envoyer aux utilisateurs d'une application.

La manière dont la clé du serveur d&#39;application privée est utilisée lors de l&#39;envoi d&#39;une
message

Techniquement, applicationServerKey est facultatif. Cependant, l'approche la plus simple dans Chrome l'exige, tandis que d'autres navigateurs peuvent l'exiger dans à l'avenir. Il est facultatif sur Firefox.

La spécification qui définit quelle doit être la clé du serveur d'applications est la spécification VAPID. Chaque fois que vous lisez des informations faisant référence à des clés de serveur d'applications ou VAPID, souvenez-vous simplement qu'il s'agit de la même chose.

Créer des clés de serveur d'application

Vous pouvez créer un ensemble public et privé de clés de serveur d'applications en accédant à web-push-codelab.glitch.me, ou vous pouvez utiliser le Ligne de commande web-push pour générer des clés en procédant comme suit:

    $ npm install -g web-push
    $ web-push generate-vapid-keys

Vous n'avez besoin de créer ces clés qu'une seule fois pour votre application. Veillez simplement à conserver clé privée privée. (Oui, je viens de le dire.)

Autorisations et abonnement()

Appeler subscribe() a un effet secondaire. Si votre application Web ne dispose pas d'autorisations pour des notifications au moment de l'appel de subscribe(), le navigateur demandera des autorisations pour vous. C'est utile si votre interface utilisateur fonctionne avec ce flux, mais si vous voulez plus (et je pense que la plupart des développeurs le feront), s'en tenir à l'API Notification.requestPermission(). que nous avons utilisés précédemment.

Qu'est-ce qu'un abonnement PushSubscription ?

Nous appelons subscribe() et transmettons certaines options. En retour, nous obtenons une promesse qui renvoie PushSubscription, ce qui génère un code semblable à celui-ci:

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

L'objet PushSubscription contient toutes les informations nécessaires à l'envoi d'un message push. des messages à cet utilisateur. Si vous imprimez le contenu à l'aide de JSON.stringify(), vous verrez suivantes:

    {
      "endpoint": "https://some.pushservice.com/something-unique",
      "keys": {
        "p256dh":
    "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
        "auth":"FPssNDTKnInHVndSTdbKFw=="
      }
    }

endpoint correspond à l'URL des services push. Pour déclencher un message push, effectuez une requête POST. à cette URL.

L'objet keys contient les valeurs utilisées pour chiffrer les données de message envoyées avec un message push. (nous y reviendrons plus tard dans cette section).

Réabonnement régulier pour éviter l'expiration

Lorsque vous vous abonnez aux notifications push, vous recevez souvent une PushSubscription.expirationTime de null. En théorie, cela signifie que l'abonnement n'expire jamais (contrairement à DOMHighResTimeStamp, qui vous indique le moment exact où l'abonnement expire). Dans la pratique, il est toutefois courant que les navigateurs laissent toujours les abonnements expirer, par exemple si aucune notification push n'a été reçue depuis plus longtemps ou si le navigateur détecte que l'utilisateur n'utilise pas une application disposant de l'autorisation de notification push. Pour éviter cela, l'un des moyens consiste à réabonner l'utilisateur à chaque notification reçue, comme illustré dans l'extrait de code suivant. Vous devez donc envoyer des notifications suffisamment fréquemment pour que le navigateur n'expire pas automatiquement. Vous devez donc évaluer très attentivement les avantages et les inconvénients des notifications légitimes par rapport à l'envoi de spam involontaire à l'utilisateur afin que l'abonnement n'expire pas. En fin de compte, vous ne devez pas essayer de vous battre contre le navigateur pour protéger l'utilisateur des abonnements aux notifications oubliés depuis longtemps.

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

Envoyer un abonnement à votre serveur

Une fois que vous disposez d'un abonnement push, vous pouvez l'envoyer à votre serveur. C'est à vous de décider comment vous mais une petite astuce consiste à utiliser JSON.stringify() pour extraire toutes les données nécessaires abonnement. Vous pouvez également assembler les mêmes manuellement, comme ceci:

const subscriptionObject = {
  endpoint: pushSubscription.endpoint,
  keys: {
    p256dh: pushSubscription.getKeys('p256dh'),
    auth: pushSubscription.getKeys('auth'),
  },
};

// The above is the same output as:

const subscriptionObjectToo = JSON.stringify(pushSubscription);

L'envoi de l'abonnement s'effectue sur la page Web comme suit:

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.');
      }
    });
}

Le serveur de nœud reçoit cette demande et enregistre les données dans une base de données pour une utilisation ultérieure.

app.post('/api/save-subscription/', function (req, res) {
  if (!isValidSaveRequest(req, res)) {
    return;
  }

  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.',
          },
        }),
      );
    });
});

Avec les détails PushSubscription sur notre serveur, nous pouvons envoyer à l'utilisateur un message à tout moment.

Réabonnement régulier pour éviter l'expiration

Lorsque vous vous abonnez aux notifications push, vous recevez souvent une PushSubscription.expirationTime de null. En théorie, cela signifie que l'abonnement n'expire jamais (contrairement à DOMHighResTimeStamp, qui vous indique le moment exact où l'abonnement expire). En pratique, il est toutefois courant que les navigateurs laissent toujours les abonnements expirer, par exemple si aucune notification push n'a été reçue pendant une longue période ou si le navigateur détecte que l'utilisateur n'utilise pas l'application disposant de l'autorisation de notification push. Pour éviter cela, l'un des moyens consiste à réabonner l'utilisateur à chaque notification reçue, comme illustré dans l'extrait de code suivant. Vous devez donc envoyer des notifications suffisamment fréquemment pour que le navigateur n'expire pas automatiquement. Vous devez donc évaluer très attentivement les avantages et les inconvénients d'un besoin de notification légitime par rapport à l'envoi de spam à l'utilisateur afin que l'abonnement n'expire pas. En fin de compte, vous ne devez pas essayer de vous battre contre le navigateur pour protéger l'utilisateur des abonnements aux notifications oubliés depuis longtemps.

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

Questions fréquentes

Voici quelques questions fréquentes posées à ce stade:

Puis-je changer le service push utilisé par un navigateur ?

Non. Le service push est sélectionné par le navigateur. Comme nous l'avons vu subscribe(), le navigateur enverra des requêtes réseau au service push pour récupérer les détails de l'abonnement PushSubscription.

Chaque navigateur utilise un service push différent, n'a-t-il pas des API différentes ?

Tous les services push attendront la même API.

Cette API courante s'appelle Protocole Web Push et décrit la requête réseau que votre application devra exécuter pour déclencher un message push.

Si j'abonne un utilisateur sur son ordinateur, le sera-t-il également sur son téléphone ?

Malheureusement non. L'utilisateur doit activer la fonctionnalité Push sur chaque navigateur qu'il souhaite utiliser. recevoir les messages. Notez également que cela nécessitera l'utilisateur accordant l'autorisation sur chaque appareil.

Étapes suivantes

Ateliers de programmation