S'abonner à un utilisateur

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

Pour ce faire, l'API JavaScript est relativement simple. Examinons donc le flux logique.

Détection de fonctionnalités

Nous devons d'abord vérifier si le navigateur actuel est réellement compatible avec les messages push. Nous pouvons vérifier si le mode push est pris en charge à l'aide de 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;
}

Bien que la compatibilité des navigateurs se développe rapidement pour les service workers et les messages push, il est toujours judicieux de détecter les fonctionnalités pour ces deux fonctionnalités et de les améliorer progressivement.

Enregistrer un service worker

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

Lorsque nous enregistrons un service worker, nous indiquons au navigateur où se trouve le fichier de notre service worker. Il s'agit toujours d'un fichier JavaScript, mais le navigateur "lui donne accès" aux API du service worker, y compris en mode push. Pour être plus précis, le navigateur exécute le fichier dans un environnement de service worker.

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 avons un fichier service worker et où il se trouve. Dans ce cas, le fichier du service worker se trouve à l'emplacement /service-worker.js. En arrière-plan, le navigateur effectue les étapes suivantes après avoir appelé register():

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

  2. Exécutez le code JavaScript.

  3. Si tout fonctionne correctement et qu'il n'y a pas d'erreur, la promesse renvoyée par register() sera résolue. En cas d'erreur de quelque nature que ce soit, la promesse sera rejetée.

Si register() refuse votre code, 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, il renvoie ServiceWorkerRegistration. Nous utiliserons cette inscription pour accéder à l'API PushManager.

Compatibilité du navigateur avec l'API PushManager

Navigateurs pris en charge

  • 42
  • 17
  • 44
  • 16

Source

Demander l'autorisation

Nous avons enregistré notre service worker et sommes prêts à abonner l'utilisateur. L'étape suivante consiste à obtenir l'autorisation de l'utilisateur pour lui envoyer des messages push.

L'API permettant d'obtenir l'autorisation est relativement simple. L'inconvénient est que l'API a récemment été remplacée par un rappel par rapport au renvoi d'une promesse. Le problème est que nous ne pouvons pas dire quelle version de l'API est implémentée par le navigateur actuel. Vous devez donc implémenter les deux et gérer les deux.

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 de Notification.requestPermission(). Cette méthode affiche une invite à l'utilisateur:

Invite d'autorisation dans Chrome pour ordinateur et mobile

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

Dans l'exemple de code ci-dessus, la promesse renvoyée par askPermission() est résolue si l'autorisation est accordée. Dans le cas contraire, une erreur est renvoyée et la promesse est rejetée.

L 'un des cas limites que vous devez gérer est le fait que l'utilisateur clique sur le bouton « Bloquer ». Dans ce cas, votre application Web ne pourra plus redemander l'autorisation à l'utilisateur. Ils devront "débloquer " manuellement votre application en modifiant son état d'autorisation, caché dans un panneau de paramètres. Réfléchissez bien à la façon dont vous demandez l'autorisation à l'utilisateur et à quel moment, car s'il clique sur "Bloquer", il n'est pas facile d'annuler cette décision.

La bonne nouvelle est que la plupart des utilisateurs sont heureux d'accorder une autorisation tant qu'ils savent pourquoi l'autorisation est demandée.

Nous verrons plus tard comment certains sites populaires demandent une autorisation.

Abonner un utilisateur avec PushManager

Une fois notre service worker enregistré et autorisé, nous pouvons abonner un utilisateur en appelant registration.pushManager.subscribe().

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

Lorsque vous appelez la méthode subscribe(), nous transmettons un objet options, composé à la fois de paramètres obligatoires et facultatifs.

Étudions toutes les options que nous pouvons transmettre.

Options userVisibleOnly

Lorsque la technologie push a été ajoutée pour la première fois aux navigateurs, les développeurs ne savaient pas si les développeurs pouvaient envoyer un message push au lieu d'afficher de notification. Cette opération est communément appelée "envoi silencieux", car l'utilisateur ne sait pas que quelque chose s'est passé en arrière-plan.

Le problème était que les développeurs pouvaient effectuer des actions désagréables, comme suivre la position d'un utilisateur de manière continue, sans que celui-ci le sache.

Pour éviter ce scénario et donner aux auteurs de spécifications le temps d'envisager la meilleure façon de prendre en charge cette fonctionnalité, l'option userVisibleOnly a été ajoutée et la transmission d'une valeur true est un accord symbolique avec le navigateur indiquant que l'application Web affichera une notification chaque fois qu'un push est reçu (c'est-à-dire, pas de push silencieux).

Pour le moment, vous devez transmettre la valeur true. Si vous n'incluez pas la clé userVisibleOnly ou transmettez false, vous obtiendrez l'erreur suivante:

Chrome n'est actuellement compatible avec l'API Push que pour les abonnements qui génèrent des messages visibles par l'utilisateur. Vous pouvez l'indiquer en appelant pushManager.subscribe({userVisibleOnly: true}) à la place. Pour en savoir plus, consultez la page https://goo.gl/yqv4Q4.

Il semble actuellement que la fonction push silencieuse globale ne sera jamais implémentée dans Chrome. Au lieu de cela, les auteurs de spécifications explorent la notion d'API budgétaire, qui permettra aux applications Web un certain 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'application" dans la section précédente. Les "clés de serveur d'applications" permettent à un service push d'identifier l'application abonnée à un utilisateur et de s'assurer que cette 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 librement.

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

Le diagramme ci-dessous illustre ces étapes.

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

Illustration de la clé publique du serveur d'applications utilisée dans la méthode d'abonnement.

Lorsque vous souhaitez envoyer ultérieurement un message push, vous devez créer un en-tête Authorization contenant des informations signées avec la clé privée de votre serveur d'application. Lorsque le service push reçoit une requête pour envoyer un message push, il peut valider cet en-tête Authorization signé en recherchant la clé publique associée au point de terminaison qui reçoit la requête. Si la signature est valide, le service push sait qu'il doit provenir du serveur d'applications et de la clé privée correspondante. Il s'agit essentiellement d'une mesure de sécurité qui empêche toute autre personne d'envoyer des messages aux utilisateurs d'une application.

Comment la clé privée du serveur d'applications est utilisée lors de l'envoi d'un message

Techniquement, le applicationServerKey est facultatif. Cependant, l'implémentation la plus simple sur Chrome l'exige, et d'autres navigateurs pourront l'exiger à l'avenir. Il est facultatif dans Firefox.

La spécification qui définit ce que doit être la clé du serveur d'applications est la spécification VAPID. Chaque fois que vous lisez des termes faisant référence aux clés de serveur d'applications ou aux clés VAPID, n'oubliez pas 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 à l'adresse web-push-codelab.glitch.me ou utiliser la 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. Assurez-vous simplement de garder la clé privée privée. (Oui, je viens de le dire.)

Autorisations et "subscribe()"

L'appel de subscribe() a un effet secondaire. Si votre application Web ne dispose pas des autorisations nécessaires pour afficher les notifications au moment de l'appel de subscribe(), le navigateur les demandera pour vous. Cela est utile si votre UI fonctionne avec ce flux, mais si vous souhaitez plus de contrôle (et je pense que la plupart des développeurs le feront), conservez l'API Notification.requestPermission() que nous avons utilisée précédemment.

Qu'est-ce qu'un abonnement PushSubscription ?

Nous appelons subscribe(), transmettons certaines options, puis nous obtenons une promesse qui se résout en 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 pour envoyer un message push à cet utilisateur. Si vous imprimez le contenu à l'aide de JSON.stringify(), vous verrez ce qui suit:

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

endpoint est l'URL du service push. Pour déclencher un message push, envoyez une requête POST à cette URL.

L'objet keys contient les valeurs utilisées pour chiffrer les données des messages envoyés avec un message push (que nous aborderons plus loin dans cette section).

Envoyer un abonnement à votre serveur

Une fois que vous disposez d'un abonnement push, vous devrez l'envoyer à votre serveur. C'est à vous de décider de la marche à suivre. Toutefois, un petit conseil consiste à utiliser JSON.stringify() pour extraire toutes les données nécessaires de l'objet d'abonnement. Vous pouvez également rassembler le même résultat 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 se fait 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 un message à l'utilisateur quand nous le souhaitons.

Questions fréquentes

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

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

Non. Le service push est sélectionné par le navigateur et, comme nous l'avons vu avec l'appel subscribe(), le navigateur envoie 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. Les API sont-elles différentes ?

Tous les services push s'attendent à recevoir la même API.

Cette API courante est appelée Web Push Protocol et décrit la requête réseau que votre application doit effectuer pour déclencher un message push.

Si je m'abonne à un utilisateur sur son ordinateur, le sont-ils également sur son téléphone ?

Malheureusement, non. Un utilisateur doit s'inscrire au service push sur chaque navigateur sur lequel il souhaite recevoir des messages. Notez également que cela nécessitera que l'utilisateur accorde une autorisation sur chaque appareil.

Étapes suivantes

Ateliers de programmation