В этой лабораторной работе вы шаг за шагом покажете, как создать сервер push-уведомлений. К концу работы у вас будет сервер, который:
- Отслеживает подписки на push-уведомления (т. е. сервер создает новую запись в базе данных, когда клиент соглашается на получение push-уведомлений, и удаляет существующую запись в базе данных, когда клиент отказывается от них)
- Отправляет push-уведомление одному клиенту
- Отправляет push-уведомление всем подписанным клиентам
Эта практическая работа направлена на обучение на практике и не слишком подробно рассматривает концепции. Подробнее о концепциях push-уведомлений читайте в статье «Как работают push-уведомления?» .
Клиентский код этой лабораторной работы уже готов. В ней вам нужно будет реализовать только сервер. Чтобы узнать, как реализовать клиент push-уведомлений, ознакомьтесь с практической работой: Создание клиента push-уведомлений .
Совместимость с браузерами
Известно, что эта лабораторная работа работает со следующими комбинациями операционных систем и браузеров:
- Windows: Chrome, Edge
- macOS: Chrome, Firefox
- Android: Chrome, Firefox
Известно, что эта лабораторная работа не работает со следующими операционными системами (или комбинациями операционной системы и браузера):
- macOS: Brave, Edge, Safari
- iOS
Стек приложений
- Сервер построен на основе Express.js .
- Библиотека web-push Node.js обрабатывает всю логику push-уведомлений.
- Данные о подписке записываются в JSON-файл с использованием lowdb .
Вам не обязательно использовать ни одну из этих технологий для реализации push-уведомлений. Мы выбрали эти технологии, потому что они обеспечивают надёжный опыт работы в рамках практического занятия.
Настраивать
Настроить аутентификацию
Прежде чем запускать push-уведомления, необходимо настроить сервер и клиент с помощью ключей аутентификации. Подробнее см. в статье «Подпись запросов протокола web push» .
- Откройте терминал.
-  В терминале выполните команду npx web-push generate-vapid-keys. Скопируйте значения закрытого и открытого ключей.
-  Откройте .envи обновитеVAPID_PUBLIC_KEYиVAPID_PRIVATE_KEY. Установите дляVAPID_SUBJECTmailto:test@test.test. Все эти значения должны быть заключены в двойные кавычки. После внесения изменений файл.envдолжен выглядеть примерно так:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
-  Откройте public/index.js.
-  Замените VAPID_PUBLIC_KEY_VALUE_HEREна значение вашего открытого ключа.
Управление подписками
Ваш клиент обрабатывает большую часть процесса подписки. Основное, что должен делать ваш сервер, — это сохранять новые подписки на push-уведомления и удалять старые. Именно эти подписки позволят вам отправлять push-уведомления клиентам в будущем. Подробнее о процессе подписки см. в статье «Подписка клиента на push-уведомления» .
Сохранить информацию о новой подписке
- Нажмите «Зарегистрировать сервис-воркера» на вкладке приложения. В поле статуса вы увидите сообщение, похожее на это:
Service worker registered. Scope: https://example.com
- На вкладке приложения нажмите «Подписаться на push-уведомления» . Ваш браузер или операционная система, вероятно, спросит вас, хотите ли вы разрешить сайту отправлять вам push-уведомления. Нажмите «Разрешить» (или любую другую эквивалентную фразу, используемую в вашем браузере/ОС). В поле статуса вы увидите сообщение, похожее на это:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
-  Откройте терминал и просмотрите логи. Вы должны увидеть строку /add-subscriptionа затем некоторые данные./add-subscription— это URL-адрес, на который клиент отправляет POST- запрос, чтобы подписаться на push-уведомления. Последующие данные — это информация о подписке клиента, которую необходимо сохранить.
-  Откройте server.js.
-  Обновите логику обработчика маршрута /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);
});
Удалить старую информацию о подписке
- Вернитесь на вкладку приложения.
- Нажмите «Отписаться от push-уведомлений» .
-  Проверьте логи ещё раз. Вы должны увидеть /remove-subscriptionа затем информацию о подписке клиента.
-  Обновите логику обработчика маршрута /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-сервис. По сути, ваш сервер просто инициирует процесс отправки сообщений клиентам, отправляя запросы к веб-сервису (запросы по протоколу web push) к веб-сервису (push-сервису), принадлежащему поставщику браузера, используемого вашим пользователем.
-  Обновите логику обработчика маршрута /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);
});
-  Обновите функцию 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} `);
      });
  });
}
-  Обновите логику обработчика маршрута /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);
  }
});
- Вернитесь на вкладку приложения.
-  Нажмите «Уведомить меня» . Вы получите push-уведомление. Заголовок должен быть Hello, Notifications!, а текст —ID: <ID>, где<ID>— случайное число.
- Откройте приложение в других браузерах или на других устройствах и попробуйте подписаться на push-уведомления, а затем нажмите кнопку «Уведомить всех» . Вы должны получать одинаковые уведомления на всех устройствах, на которые вы подписаны (т.е. идентификатор в тексте push-уведомления должен быть одинаковым).
Следующие шаги
- Прочитайте обзор push-уведомлений для более глубокого концептуального понимания того, как работают push-уведомления.
- Ознакомьтесь с практической работой: создание клиента push-уведомлений, чтобы узнать, как создать клиент, который запрашивает разрешение на получение уведомлений, подписывает устройство на получение push-уведомлений и использует service worker для получения push-сообщений и отображения сообщений в виде уведомлений.
 
 
        
        