Codelab: создание сервера push-уведомлений

Кейт Джеффрис
Kate Jeffreys

В этой кодовой лаборатории шаг за шагом показано, как создать сервер push-уведомлений. К концу работы над кодом у вас будет сервер, который:

  • Отслеживает подписки на push-уведомления (т. е. сервер создает новую запись в базе данных, когда клиент соглашается на push-уведомления, и удаляет существующую запись базы данных, когда клиент отказывается).
  • Отправляет push-уведомление одному клиенту
  • Отправляет push-уведомление всем подписанным клиентам

Цель этой лаборатории кода – помочь вам учиться на практике, и в ней мало говорится о концепциях. Узнайте , как работают push-уведомления? узнать о концепциях push-уведомлений.

Клиентский код этой лаборатории уже готов. В этой лаборатории кода вы будете реализовывать только сервер. Чтобы узнать, как реализовать клиент push-уведомлений, ознакомьтесь с Codelab: Создание клиента push-уведомлений .

Ознакомьтесь с push-notifications-server-codelab-complete ( source ), чтобы увидеть полный код.

Совместимость с браузером

Известно, что эта кодовая лаборатория работает со следующими комбинациями операционной системы и браузера:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Андроид: Хром, Фаерфокс.

Известно, что эта кодовая лаборатория не работает со следующими операционными системами (или комбинациями операционной системы и браузера):

  • macOS: Brave, Edge, Safari
  • iOS

Стек приложений

  • Сервер построен на основе Express.js .
  • Библиотека web-push Node.js обрабатывает всю логику push-уведомлений.
  • Данные о подписке записываются в файл JSON с помощью lowdb .

Вам не обязательно использовать какую-либо из этих технологий для реализации push-уведомлений. Мы выбрали эти технологии, потому что они обеспечивают надежную работу в лаборатории.

Настраивать

Получите редактируемую копию кода

Редактор кода, который вы видите справа от этих инструкций, в этой лаборатории кода будет называться Glitch UI .

  1. Нажмите Remix to Edit, чтобы сделать проект доступным для редактирования.

Настройка аутентификации

Прежде чем вы сможете заставить работать push-уведомления, вам необходимо настроить на сервере и клиенте ключи аутентификации. См. раздел Подписание запросов протокола веб-push, чтобы узнать, почему.

  1. Откройте терминал Glitch, нажав «Инструменты» , а затем «Терминал» .
  2. В терминале запустите npx web-push generate-vapid-keys . Скопируйте значения закрытого и открытого ключей.
  3. Откройте .env и обновите VAPID_PUBLIC_KEY и VAPID_PRIVATE_KEY . Установите для VAPID_SUBJECT mailto:test@test.test . Все эти значения должны быть заключены в двойные кавычки. После внесения обновлений ваш файл .env должен выглядеть примерно так:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Закройте терминал Glitch.
  1. Откройте public/index.js .
  2. Замените VAPID_PUBLIC_KEY_VALUE_HERE значением вашего открытого ключа.

Управление подписками

Ваш клиент берет на себя большую часть процесса подписки. Основное, что нужно сделать вашему серверу, — это сохранить новые подписки на push-уведомления и удалить старые подписки. Эти подписки позволят вам отправлять сообщения клиентам в будущем. Дополнительную информацию о процессе подписки см. в разделе Подписка клиента на push-уведомления .

Сохраните новую информацию о подписке

  1. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим полноэкранный .
  1. Нажмите «Зарегистрировать сервисного работника» на вкладке приложения. В поле статуса вы должны увидеть сообщение, подобное этому:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. На вкладке приложения нажмите «Подписаться», чтобы отправить рассылку . Ваш браузер или операционная система, вероятно, спросят вас, хотите ли вы, чтобы веб-сайт отправлял вам push-уведомления. Нажмите «Разрешить» (или любую аналогичную фразу, которую использует ваш браузер/ОС). В поле статуса вы должны увидеть сообщение, подобное этому:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. Вернитесь к своему коду, нажав «Просмотреть исходный код» в пользовательском интерфейсе Glitch.
  2. Откройте журналы сбоев, нажав «Инструменты» , а затем « Журналы» . Вы должны увидеть /add-subscription за которым следуют некоторые данные. /add-subscription — это URL-адрес, на который клиент отправляет запрос POST , когда хочет подписаться на push-уведомления. Следующие данные представляют собой информацию о подписке клиента, которую необходимо сохранить.
  3. Откройте server.js .
  4. Обновите логику обработчика маршрута /add-subscription используя следующий код:
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);
});

Удалить старую информацию о подписке

  1. Вернитесь на вкладку приложения.
  2. Нажмите «Отписаться от push» .
  3. Посмотрите еще раз журналы сбоев. Вы должны увидеть /remove-subscription за которым следует информация о подписке клиента.
  4. Обновите логику обработчика маршрута /remove-subscription используя следующий код:
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);
});

Отправлять уведомления

Как объяснено в разделе «Отправка push-сообщения» , ваш сервер на самом деле не отправляет push-сообщения напрямую клиентам. Скорее, для этого он полагается на службу push. По сути, ваш сервер просто запускает процесс отправки сообщений клиентам, отправляя запросы веб-службы (запросы протокола веб-push) к веб-службе (службе push), принадлежащей поставщику браузера, который использует ваш пользователь.

  1. Обновите логику обработчика маршрута /notify-me используя следующий код:
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. Обновите функцию sendNotifications() следующим кодом:
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. Обновите логику обработчика маршрута /notify-all используя следующий код:
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. Вернитесь на вкладку приложения.
  2. Нажмите «Отменить подписку на рассылку» , а затем нажмите «Подписаться», чтобы повторить рассылку . Это необходимо только потому, что, как упоминалось ранее, Glitch перезапускает проект каждый раз, когда вы редактируете код, и проект настроен на удаление базы данных при запуске.
  3. Нажмите «Уведомить меня» . Вы должны получить push-уведомление. Заголовок должен быть Hello, Notifications! и тело должно иметь ID: <ID> , где <ID> — случайное число.
  4. Откройте свое приложение в других браузерах или устройствах и попробуйте подписаться на них для получения push-уведомлений, а затем нажмите кнопку «Уведомить всех» . Вы должны получить одно и то же уведомление на всех своих подписанных устройствах (т. е. идентификатор в теле push-уведомления должен быть одинаковым).

Следующие шаги

  • Прочтите обзор push-уведомлений , чтобы получить более глубокое концептуальное понимание того, как работают push-уведомления.
  • Ознакомьтесь с Codelab: Создание клиента push-уведомлений, чтобы узнать, как создать клиент, который запрашивает разрешение на уведомление, подписывает устройство на получение push-уведомлений и использует сервисного работника для получения push-сообщений и отображения сообщений в виде уведомлений.
,

Кейт Джеффрис
Kate Jeffreys

В этой кодовой лаборатории шаг за шагом показано, как создать сервер push-уведомлений. К концу работы над кодом у вас будет сервер, который:

  • Отслеживает подписки на push-уведомления (т. е. сервер создает новую запись в базе данных, когда клиент соглашается на push-уведомления, и удаляет существующую запись базы данных, когда клиент отказывается).
  • Отправляет push-уведомление одному клиенту
  • Отправляет push-уведомление всем подписанным клиентам

Цель этой лаборатории кода – помочь вам учиться на практике, и в ней мало говорится о концепциях. Узнайте , как работают push-уведомления? узнать о концепциях push-уведомлений.

Клиентский код этой лаборатории уже готов. В этой лаборатории кода вы будете реализовывать только сервер. Чтобы узнать, как реализовать клиент push-уведомлений, ознакомьтесь с Codelab: Создание клиента push-уведомлений .

Ознакомьтесь с push-notifications-server-codelab-complete ( source ), чтобы увидеть полный код.

Совместимость с браузером

Известно, что эта кодовая лаборатория работает со следующими комбинациями операционной системы и браузера:

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Андроид: Хром, Фаерфокс.

Известно, что эта кодовая лаборатория не работает со следующими операционными системами (или комбинациями операционной системы и браузера):

  • macOS: Brave, Edge, Safari
  • iOS

Стек приложений

  • Сервер построен на основе Express.js .
  • Библиотека web-push Node.js обрабатывает всю логику push-уведомлений.
  • Данные о подписке записываются в файл JSON с помощью lowdb .

Вам не обязательно использовать какую-либо из этих технологий для реализации push-уведомлений. Мы выбрали эти технологии, потому что они обеспечивают надежную работу в лаборатории.

Настраивать

Получите редактируемую копию кода

Редактор кода, который вы видите справа от этих инструкций, в этой лаборатории кода будет называться Glitch UI .

  1. Нажмите Remix to Edit, чтобы сделать проект доступным для редактирования.

Настройка аутентификации

Прежде чем вы сможете заставить работать push-уведомления, вам необходимо настроить на сервере и клиенте ключи аутентификации. См. раздел Подписание запросов протокола веб-push, чтобы узнать, почему.

  1. Откройте терминал Glitch, нажав «Инструменты» , а затем «Терминал» .
  2. В терминале запустите npx web-push generate-vapid-keys . Скопируйте значения закрытого и открытого ключей.
  3. Откройте .env и обновите VAPID_PUBLIC_KEY и VAPID_PRIVATE_KEY . Установите для VAPID_SUBJECT mailto:test@test.test . Все эти значения должны быть заключены в двойные кавычки. После внесения обновлений ваш файл .env должен выглядеть примерно так:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Закройте терминал Glitch.
  1. Откройте public/index.js .
  2. Замените VAPID_PUBLIC_KEY_VALUE_HERE значением вашего открытого ключа.

Управление подписками

Ваш клиент берет на себя большую часть процесса подписки. Основное, что нужно сделать вашему серверу, — это сохранить новые подписки на push-уведомления и удалить старые подписки. Эти подписки позволят вам отправлять сообщения клиентам в будущем. Дополнительную информацию о процессе подписки см. в разделе Подписка клиента на push-уведомления .

Сохраните новую информацию о подписке

  1. Чтобы просмотреть сайт, нажмите «Просмотреть приложение» . Затем нажмите Полноэкранный режим полноэкранный .
  1. Нажмите «Зарегистрировать сервисного работника» на вкладке приложения. В поле статуса вы должны увидеть сообщение, подобное этому:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. На вкладке приложения нажмите «Подписаться», чтобы отправить рассылку . Ваш браузер или операционная система, вероятно, спросят вас, хотите ли вы, чтобы веб-сайт отправлял вам push-уведомления. Нажмите «Разрешить» (или любую аналогичную фразу, которую использует ваш браузер/ОС). В поле статуса вы должны увидеть сообщение, подобное этому:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. Вернитесь к своему коду, нажав «Просмотреть исходный код» в пользовательском интерфейсе Glitch.
  2. Откройте журналы сбоев, нажав «Инструменты» , а затем « Журналы» . Вы должны увидеть /add-subscription за которым следуют некоторые данные. /add-subscription — это URL-адрес, на который клиент отправляет запрос POST , когда хочет подписаться на push-уведомления. Следующие данные представляют собой информацию о подписке клиента, которую необходимо сохранить.
  3. Откройте server.js .
  4. Обновите логику обработчика маршрута /add-subscription используя следующий код:
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);
});

Удалить старую информацию о подписке

  1. Вернитесь на вкладку приложения.
  2. Нажмите «Отписаться от push» .
  3. Посмотрите еще раз журналы сбоев. Вы должны увидеть /remove-subscription за которым следует информация о подписке клиента.
  4. Обновите логику обработчика маршрута /remove-subscription используя следующий код:
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);
});

Отправлять уведомления

Как объяснено в разделе «Отправка push-сообщения» , ваш сервер на самом деле не отправляет push-сообщения напрямую клиентам. Скорее, для этого он полагается на службу push. По сути, ваш сервер просто запускает процесс отправки сообщений клиентам, отправляя запросы веб-службы (запросы протокола веб-push) к веб-службе (службе push), принадлежащей поставщику браузера, который использует ваш пользователь.

  1. Обновите логику обработчика маршрута /notify-me используя следующий код:
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. Обновите функцию sendNotifications() следующим кодом:
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. Обновите логику обработчика маршрута /notify-all используя следующий код:
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. Вернитесь на вкладку приложения.
  2. Нажмите «Отменить подписку на рассылку» , а затем нажмите «Подписаться», чтобы повторить рассылку . Это необходимо только потому, что, как упоминалось ранее, Glitch перезапускает проект каждый раз, когда вы редактируете код, и проект настроен на удаление базы данных при запуске.
  3. Нажмите «Уведомить меня» . Вы должны получить push-уведомление. Заголовок должен быть Hello, Notifications! и тело должно иметь ID: <ID> , где <ID> — случайное число.
  4. Откройте свое приложение в других браузерах или устройствах и попробуйте подписаться на push-уведомления, а затем нажмите кнопку «Уведомить всех» . Вы должны получить одно и то же уведомление на всех своих подписанных устройствах (т. е. идентификатор в теле push-уведомления должен быть одинаковым).

Следующие шаги

  • Прочтите обзор push-уведомлений , чтобы получить более глубокое концептуальное понимание того, как работают push-уведомления.
  • Ознакомьтесь с Codelab: Создание клиента push-уведомлений, чтобы узнать, как создать клиент, который запрашивает разрешение на уведомление, подписывает устройство на получение push-уведомлений и использует сервисного работника для получения push-сообщений и отображения сообщений в виде уведомлений.