Codelab: criar um servidor de notificações push

Kate Jeffreys
Kate Jeffreys
Kayce Basques
Kayce Basques

Este codelab mostra, etapa por etapa, como criar um servidor de notificações push. Ao final do codelab, você terá um servidor que:

  • Rastreia as inscrições de notificações push (ou seja, o servidor cria um novo registro de banco de dados quando um cliente ativa as notificações push e exclui um registro de banco de dados existente quando um cliente desativa).
  • Envia uma notificação push para um único cliente.
  • Envia uma notificação push para todos os clientes inscritos.

O foco deste codelab é ajudar você a aprender na prática, sem falar muito sobre conceitos. Confira Como as notificações push funcionam? para saber mais sobre os conceitos de notificações push.

O código do cliente deste codelab já está completo. Neste codelab, você vai implementar apenas o servidor. Para saber como implementar um cliente de notificação push, confira Codelab: crie um cliente de notificação push.

Compatibilidade com navegadores

Este codelab funciona com as seguintes combinações de sistema operacional e navegador:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Android: Chrome, Firefox

Este codelab não funciona com os seguintes sistemas operacionais (ou combinações de sistema operacional e navegador):

  • macOS: Brave, Edge, Safari
  • iOS

Pilha de aplicativos

  • O servidor é criado com base no Express.js.
  • A biblioteca web-push do Node.js processa toda a lógica de notificação push.
  • Os dados de assinatura são gravados em um arquivo JSON usando lowdb.

Não é necessário usar nenhuma dessas tecnologias para implementar notificações push. Escolhemos essas tecnologias porque elas oferecem uma experiência de codelab confiável.

Configuração

Configurar a autenticação

Antes de receber notificações push, é necessário configurar o servidor e o cliente com chaves de autenticação. Consulte Assinar suas solicitações de protocolo push da Web para saber o motivo.

  1. Abra o terminal.
  2. No terminal, execute npx web-push generate-vapid-keys. Copie os valores da chave privada e da chave pública.
  3. Abra .env e atualize VAPID_PUBLIC_KEY e VAPID_PRIVATE_KEY. Defina VAPID_SUBJECT como mailto:test@test.test. Todos esses valores precisam estar entre aspas duplas. Depois de fazer as atualizações, seu arquivo .env vai ficar parecido com este:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Abra public/index.js.
  2. Substitua VAPID_PUBLIC_KEY_VALUE_HERE pelo valor da sua chave pública.

Gerenciar assinaturas

O cliente processa a maior parte do processo de assinatura. As principais ações que seu servidor precisa realizar são salvar novas assinaturas de notificações push e excluir as antigas. Essas assinaturas permitem que você envie mensagens para clientes no futuro. Consulte Inscrever o cliente para receber notificações push para mais contexto sobre o processo de inscrição.

Salvar novas informações de assinatura

  1. Clique em Registrar service worker na guia do app. Na caixa de status, você vai ver uma mensagem semelhante a esta:
Service worker registered. Scope: https://example.com
  1. Na guia do app, clique em Inscrever-se para receber notificações push. Seu navegador ou sistema operacional provavelmente vai perguntar se você quer permitir que o site envie notificações push. Clique em Permitir ou na frase equivalente que seu navegador/SO usa. Na caixa de status, você vai encontrar uma mensagem semelhante a esta:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. Abra o terminal para conferir os registros. Você vai ver /add-subscription seguido de alguns dados. /add-subscription é o URL para onde o cliente envia uma solicitação POST quando quer se inscrever para receber notificações push. Os dados a seguir são as informações de assinatura do cliente que você precisa salvar.
  2. Abra server.js.
  3. Atualize a lógica do gerenciador de rotas /add-subscription com o seguinte código:
app.post('/add-subscription', (request, response) => {
  console.log('/add-subscription');
  console.log(request.body);
  console.log(`Subscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .push(request.body)
    .write();
  response.sendStatus(200);
});

Excluir informações antigas de assinatura

  1. Volte para a guia do app.
  2. Clique em Cancelar inscrição nas notificações push.
  3. Confira os registros novamente. Você vai ver /remove-subscription seguido pelas informações de assinatura do cliente.
  4. Atualize a lógica do gerenciador de rotas /remove-subscription com o seguinte código:
app.post('/remove-subscription', (request, response) => {
  console.log('/remove-subscription');
  console.log(request.body);
  console.log(`Unsubscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .remove({endpoint: request.body.endpoint})
    .write();
  response.sendStatus(200);
});

Envie notificações

Conforme explicado em Enviar uma mensagem push, seu servidor não envia as mensagens push diretamente aos clientes. Em vez disso, ele depende de um serviço de push para fazer isso. Basicamente, seu servidor inicia o processo de envio de mensagens aos clientes fazendo solicitações de serviço da Web (solicitações de protocolo de push da Web) para um serviço da Web (o serviço de push) de propriedade do fornecedor do navegador usado pelo usuário.

  1. Atualize a lógica do gerenciador de rotas /notify-me com o seguinte código:
app.post('/notify-me', (request, response) => {
  console.log('/notify-me');
  console.log(request.body);
  console.log(`Notifying ${request.body.endpoint}`);
  const subscription = 
      db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
  sendNotifications([subscription]);
  response.sendStatus(200);
});
  1. Atualize a função sendNotifications() com o seguinte código:
function sendNotifications(subscriptions) {
  // TODO
  // Create the notification content.
  const notification = JSON.stringify({
    title: "Hello, Notifications!",
    options: {
      body: `ID: ${Math.floor(Math.random() * 100)}`
    }
  });
  // Customize how the push service should attempt to deliver the push message.
  // And provide authentication information.
  const options = {
    TTL: 10000,
    vapidDetails: vapidDetails
  };
  // Send a push message to each client specified in the subscriptions array.
  subscriptions.forEach(subscription => {
    const endpoint = subscription.endpoint;
    const id = endpoint.substr((endpoint.length - 8), endpoint.length);
    webpush.sendNotification(subscription, notification, options)
      .then(result => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Result: ${result.statusCode}`);
      })
      .catch(error => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Error: ${error} `);
      });
  });
}
  1. Atualize a lógica do gerenciador de rotas /notify-all com o seguinte código:
app.post('/notify-all', (request, response) => {
  console.log('/notify-all');
  response.sendStatus(200);
  console.log('Notifying all subscribers');
  const subscriptions =
      db.get('subscriptions').cloneDeep().value();
  if (subscriptions.length > 0) {
    sendNotifications(subscriptions);
    response.sendStatus(200);
  } else {
    response.sendStatus(409);
  }
});
  1. Volte para a guia do app.
  2. Clique em Me avise. Você vai receber uma notificação push. O título precisa ser Hello, Notifications! e o corpo precisa ser ID: <ID>, em que <ID> é um número aleatório.
  3. Abra o app em outros navegadores ou dispositivos e tente inscrever-se nas notificações push e clique no botão Notificar todos. Você vai receber a mesma notificação em todos os dispositivos inscritos (ou seja, o ID no corpo da notificação push será o mesmo).

Próximas etapas