Wysyłanie wiadomości za pomocą bibliotek Web Push

Ważnym problemem podczas pracy z funkcją push jest to, że „dziwacznie”. Aby aktywować komunikat push, aplikacja musi wykonać żądanie POST usługa podążająca za web push . Aby używać przekazywania dalej przeglądarki, w których musisz używać protokołu VAPID (inaczej klucze serwera aplikacji), które w zasadzie wymagają ustawienia nagłówka z wartością potwierdzającą Twoja aplikacja może wysyłać wiadomości do użytkownika. Aby wysyłać dane za pomocą wiadomości push, muszą one zaszyfrowane i określone nagłówki musi zostać dodany, aby przeglądarka mogła poprawnie odszyfrować wiadomość.

Główny problem związany z wywołaniem wypychania polega na tym, że jeśli trafisz na problem, trudno go zdiagnozować. i rozpoznają problem. Poprawia się to wraz z upływem czasu i większą obsługą przeglądarek, ale nie jest to już łatwe. Dla: dlatego zdecydowanie zalecam korzystanie z biblioteki do szyfrowania, formatowania i w wywołaniu wiadomości push.

Jeśli naprawdę chcecie się dowiedzieć, co robią biblioteki, porozmawiamy o tym w następnej sekcji. Na razie przyjrzymy się zarządzaniu subskrypcjami i używaniu do wysyłania żądań push.

W tej sekcji użyjemy węzła web-push Biblioteka. Różnice pojawiają się w innych językach, ale nie będą zbyt różne. Patrzymy na Node, bo jest to JavaScript i powinien być które są przystępne dla czytelników.

Wykonamy te czynności:

  1. Wyślij subskrypcję do naszego backendu i zapisz ją.
  2. Odzyskaj zapisane subskrypcje i wysyłaj wiadomości push.

Zapisuję subskrypcje

Zapisywanie reguł PushSubscription w bazie danych i wysyłanie do nich zapytań będzie się różnić w zależności od języka i bazy danych po stronie serwera, ale warto zobaczyć, przykład, jak można to zrobić.

Na stronie demonstracyjnej żądanie PushSubscription jest wysyłane do naszego backendu przez proste żądanie POST:

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

Serwer Express w naszej wersji demonstracyjnej ma detektor żądań pasujący do Punkt końcowy /api/save-subscription/:

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

Na tej trasie weryfikujemy subskrypcję, by upewnić się, że żądanie jest prawidłowe i nie zawiera Pamięć:

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

Jeśli subskrypcja jest ważna, musimy ją zapisać i zwrócić odpowiednią Odpowiedź 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.',
        },
      }),
    );
  });

Ta wersja demonstracyjna używa pliku nedb do przechowywania subskrypcji. Jest to opartej na plikach, ale możesz użyć dowolnej bazy danych. Używamy tego tylko jako Nie wymaga konfiguracji. W środowisku produkcyjnym warto zastosować coś bardziej niezawodnego. (zwykle zalecamy korzystanie ze starej wersji MySQL).

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

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

Wysyłanie wiadomości push

Wysyłając komunikat push, ostatecznie potrzebujemy zdarzenia, które aktywuje proces wysyłając wiadomość do użytkowników. Popularnym sposobem jest utworzenie strony administracyjnej, na której można skonfigurować i aktywować wiadomość push. Możesz jednak utworzyć program działający lokalnie lub w dowolnym innej metody, która pozwala uzyskać dostęp do listy zasobów PushSubscription i uruchamiać kod powoduje uruchomienie komunikatu push.

Nasza wersja demonstracyjna ma „polubienie administratora” która pozwala wywoływać metodę push. To jest tylko wersja demonstracyjna, więc stronie publicznej.

Omówię każdy krok wymagany do uruchomienia wersji demonstracyjnej. Nie, kochanie aby każdy, nawet początkujący użytkowników Node, mógł się z nimi zapoznać.

Gdy rozmawialiśmy o subskrypcji użytkownika, wspomnieliśmy o dodaniu elementu applicationServerKey do Opcje: subscribe(). Ten klucz prywatny będzie potrzebny w backendzie.

W wersji demonstracyjnej wartości te są dodawane do naszej aplikacji Node w podobny sposób (nudny kod, który znam, ale wiesz, że nie ma tu magii):

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

Następnie musimy zainstalować moduł web-push dla naszego serwera węzłów:

npm install web-push --save

Następnie w skrypcie Node wymaga modułu web-push, np.:

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

Teraz możemy zacząć korzystać z modułu web-push. Najpierw musimy opowiedzieć modułowi web-push o tym, kluczy serwera aplikacji. (Pamiętaj, że są one również nazywane kluczami VAPID, ponieważ to właśnie nazwa specyfikacji).

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

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

Dodaliśmy też link „mailto:” ciągu znaków. Musi to być adres URL lub element mailto adresu e-mail. Te informacje zostaną wysłane do usługi Web push w ramach żądania wypchnięcia. Dzieje się tak, ponieważ jeśli usługa web push wymaga, skontaktować się z nadawcą, mają pewne informacje, które to umożliwiają.

Dzięki temu moduł web-push jest gotowy do użycia. Kolejnym krokiem jest uruchomienie komunikatu push.

Wersja demonstracyjna aktywuje wiadomości push za pomocą panelu administracyjnego z udawaniem.

Zrzut ekranu strony administracyjnej.

Kliknięcie opcji „Uruchom wiadomość push”. wyśle żądanie POST do /api/trigger-push-msg/, który jest sygnałem dla naszego backendu do wysyłania wiadomości push, więc tworzymy trasę Express dla tego punktu końcowego:

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

Po otrzymaniu tego żądania pobieramy subskrypcje z bazy danych, wysyła wiadomość push.

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

Funkcja triggerPushMsg() może następnie użyć biblioteki web-push, aby wysłać wiadomość do w ramach obsługiwanej subskrypcji.

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

Wywołanie webpush.sendNotification() zwróci obietnicę. Jeśli została wysłana, obietnica zostanie rozwiązana i istnieje nic nie trzeba robić. Jeśli obietnica zostanie odrzucona, przejrzyj informujący, czy PushSubscription jest wciąż prawidłowe lub nieprawidłowe.

Aby określić typ błędu usługi push, najlepiej jest zapoznać się z kodem stanu. Błąd wiadomości różnią się w zależności od usługi push, a niektóre z nich są bardziej przydatne niż inne.

W tym przykładzie sprawdza ono kody stanu 404 i 410, które są kodami stanu HTTP protokołu „Nie znaleziono” i „Brak”. Jeśli otrzymamy któryś z nich, będzie to oznaczać, że subskrypcja wygasła. lub utracił ważność. W takich sytuacjach musimy usunąć subskrypcje z naszej bazy danych.

W przypadku innego błędu wystarczy throw err, co sprawi, że obietnica zwrócona przez Odrzucono: triggerPushMsg().

Niektóre inne kody stanu omówimy w następnej sekcji, w której analizujemy funkcje push .

Po pętli subskrypcji musimy zwrócić odpowiedź 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}'`
    }
}));
});

Omówiliśmy główne etapy wdrożenia:

  1. Utwórz interfejs API, aby wysyłać subskrypcje z naszej strony internetowej do naszego backendu aby zapisać je w bazie danych.
  2. Utwórz interfejs API do aktywowania wysyłania wiadomości push (w tym przypadku interfejs API jest wywoływany z udanego panelu administracyjnego).
  3. Pobierz wszystkie subskrypcje z naszego backendu i wysyłaj do każdej z nich wiadomość za pomocą jednego z metod web-push .

Niezależnie od backendu (Node, PHP, Python itp.), kroki wdrażania push nie zmieniała się.

Teraz zastanówmy się, do czego służą te biblioteki push?

Co dalej

Ćwiczenia z kodowania