Envía mensajes con bibliotecas web push

Uno de los puntos débiles cuando se trabaja con web push es que activar un mensaje push es "difícilmente". Para activar un mensaje push, una aplicación debe enviar una solicitud POST a un después de la implementación web push protocolo. Para usar push en todos navegadores en los que necesitas usar VAPID (también conocido como claves de servidor de aplicaciones), que básicamente requiere configurar un encabezado con una prueba de valor tu aplicación puede enviar mensajes a un usuario. Para enviar datos con un mensaje push, estos deben encriptados y encabezados específicos se deben agregar para que el navegador pueda desencriptar el mensaje correctamente.

El principal problema con la activación del envío es que si se encuentra un problema, es difícil de diagnosticar el problema. Esto está mejorando con el tiempo y la compatibilidad con más navegadores, pero no es nada fácil. Para por este motivo, te recomiendo encarecidamente que uses una biblioteca para manejar la encriptación, el formateo y de activación de tu mensaje de envío.

Si realmente quieres saber qué hacen las bibliotecas, en la siguiente sección. Por ahora, veremos cómo administrar suscripciones y usar un biblioteca web push existente para realizar las solicitudes de envío.

En esta sección, usaremos el nodo web-push biblioteca. En otros idiomas, habrá diferencias, no serán muy diferentes. Estamos analizando Node, ya que es JavaScript y debería ser el más accesible para los lectores.

Sigue estos pasos:

  1. Envía una suscripción a nuestro backend y guárdala.
  2. Recupera suscripciones guardadas y activa un mensaje de envío.

Cómo guardar suscripciones

Guardar y consultar PushSubscription de una base de datos variará según la elección de lenguaje y base de datos del servidor, pero podría ser útil un ejemplo de cómo se podría hacer.

En la página web de demostración, se envía PushSubscription a nuestro backend mediante una solicitud POST simple:

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

El servidor Express de nuestra demostración tiene un objeto de escucha de solicitudes coincidente para la Extremo /api/save-subscription/:

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

En esta ruta, validamos la suscripción solo para asegurarnos de que la solicitud sea correcta y no esté llena de no utilizados:

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 la suscripción es válida, tendremos que guardarla y devolver una Respuesta 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.',
        },
      }),
    );
  });

Esta demostración usa nedb para almacenar las suscripciones, es un o una base de datos simple basada en archivos, pero puedes usar cualquier base de datos que desees. Solo los usamos como no requiere configuración. Para la producción, debes usar algo más confiable. (Tienzo a quédate con el buen MySQL).

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

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

Envía mensajes push

Cuando se trata de enviar un mensaje push, necesitamos algún evento para activar enviar un mensaje a los usuarios. Un enfoque común es crear una página de administrador que te permita configurar y activar el mensaje de envío. Pero podrías crear un programa para que se ejecute localmente o cualquier otro enfoque que permita acceder a la lista de PushSubscription y ejecutar el código para activar el mensaje de envío.

Nuestra demostración tiene un “Me gusta” de administrador que te permite activar un envío. Como es solo una demostración, página pública.

Voy a repasar cada paso del proceso para hacer que la demostración funcione. Será un bebé pasos para que todos puedan seguirlos, incluso cualquiera que sea nuevo en Node.

Cuando analizamos la suscripción de un usuario, vimos cómo agregar un applicationServerKey al Opciones de subscribe(). Necesitaremos esta clave privada en el backend.

En la demostración, estos valores se agregan a nuestra app de Node de esta manera (conozco un código aburrido, pero solo quiero que sepas que no hay magia):

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

A continuación, debemos instalar el módulo web-push para nuestro servidor de Node:

npm install web-push --save

Luego, en nuestra secuencia de comandos de Node, necesitamos el módulo web-push. así:

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

Ahora podemos comenzar a usar el módulo web-push. Primero, necesitamos informarle al módulo web-push lo siguiente: las claves del servidor de la aplicación. Recuerde que también se conocen como claves VAPID porque ese es el nombre de la especificación).

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

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

Ten en cuenta que también incluimos un mensaje "mailto:" una cadena vacía. Esta cadena debe ser una URL o un mailto de correo electrónico de Google. Esta información se enviará al servicio web push como parte del la solicitud para activar un envío. Esto se hace para que, si un servicio web push comunicarse con el remitente, este tiene información que le permitirá hacerlo.

Con esto, el módulo web-push está listo para usarse. El siguiente paso es activar un mensaje push.

La demostración usa el panel de administración ficticio para activar los mensajes de envío.

Captura de pantalla de la página Administrador.

Hacer clic en “Activar mensaje push” realizará una solicitud POST a /api/trigger-push-msg/, que es la señal para que nuestro backend envíe mensajes de envío, así que creamos la ruta exprés para este extremo:

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

Cuando se recibe esta solicitud, tomamos las suscripciones de la base de datos y para cada uno, activamos un mensaje de envío.

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 función triggerPushMsg() puede usar la biblioteca web-push para enviar un mensaje a suscripción proporcionada.

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

La llamada a webpush.sendNotification() mostrará una promesa. Si el botón el mensaje se envió con éxito, se resolverá la promesa y hay ni nada de lo que debamos hacer. Si se rechaza la promesa, debes examinar ya que te informará si el PushSubscription aún son válidas o no.

Para determinar el tipo de error de un servicio push, lo mejor es observar el código de estado. Error los mensajes varían entre los servicios push y algunos son más útiles que otros.

En este ejemplo, comprueba los códigos de estado 404 y 410, que son los códigos de estado HTTP para “No encontrado” y "Gone". Si recibimos uno de estos, significa que la suscripción venció o ya no es válida. En estos casos, debemos quitar las suscripciones de nuestra base de datos.

En caso de otro error, solo throw err, lo que hará que la promesa que devuelva el triggerPushMsg() rechazos.

Abordaremos otros de los códigos de estado en la siguiente sección cuando veamos el sitio web push protocolo de enlace en más detalle.

Después de repetir indefinidamente las suscripciones, debemos mostrar una respuesta 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}'`
    }
}));
});

Ya repasamos los pasos principales de la implementación:

  1. Crear una API para enviar suscripciones desde nuestra página web hasta nuestro backend para guardarlos en una base de datos.
  2. Crea una API para activar el envío de mensajes de envío (en este caso, un se llama a la API desde el panel de administración simulado).
  3. Recuperar todas las suscripciones de nuestro backend y enviar un mensaje a cada suscripción con una de las solicitudes web-push bibliotecas.

Sin importar tu backend (Node, PHP, Python, etc.), los pasos para implementar push son los siguientes: sean iguales.

A continuación, ¿qué hacen exactamente por nosotros estas bibliotecas push web?

Próximos pasos

Code labs