Start · Sprachen · JavaScript · Referenz · PushSubscription.options

PushSubscription.options

Eigenschaft

Schreibgeschütztes Objekt mit den Optionen (<code>userVisibleOnly</code>, <code>applicationServerKey</code>), mit denen das Push-Abonnement erstellt wurde.

seit JavaScript Baseline 2023 (Chrome 53+, Firefox 75+, Safari 16+ Kategorie: webapi

Signatur

PushSubscription.options

Beschreibung

Die schreibgeschützte Eigenschaft options einer PushSubscription liefert ein Objekt mit den Optionen, die beim Aufruf von PushManager.subscribe() übergeben wurden. Es enthält die Felder userVisibleOnly (boolean) und applicationServerKey (ArrayBuffer oder null).

Wichtig ist das vor allem bei der Rotation des VAPID-Schlüssels: Wenn der Server einen neuen öffentlichen Schlüssel verwendet, kann die Anwendung über subscription.options.applicationServerKey prüfen, ob ein bestehendes Abonnement noch mit dem aktuellen Schlüssel erstellt wurde. Falls nicht, wird es gekündigt und neu angelegt.

Der applicationServerKey wird immer als ArrayBuffer zurückgegeben, auch wenn beim Abonnieren ein Base64url-String oder ein Uint8Array übergeben wurde. Für einen Vergleich muss man beide Seiten also in dieselbe Darstellung umwandeln.

Rückgabewert

Typ
{ userVisibleOnly: boolean, applicationServerKey: ArrayBuffer | null }
Beschreibung
Objekt mit den beim Abonnieren verwendeten Optionen. applicationServerKey ist der öffentliche VAPID-Schlüssel des Anwendungsservers als ArrayBuffer, oder null, wenn keiner angegeben wurde.

Beispiele

Optionen eines bestehenden Abonnements auslesen

const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();

if (subscription) {
  const { userVisibleOnly, applicationServerKey } = subscription.options;
  console.log('userVisibleOnly:', userVisibleOnly);
  console.log('Schlüssellänge:', applicationServerKey?.byteLength);
}
userVisibleOnly: true Schlüssellänge: 65

Abonnement erneuern, wenn sich der VAPID-Schlüssel geändert hat

const VAPID_PUBLIC_KEY = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';

// Base64url -> Uint8Array
const base64UrlToBytes = (str) => {
  const padded = str.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat((4 - (str.length % 4)) % 4);
  return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
};

const sameKey = (buffer, bytes) => {
  if (!buffer) return false;
  const a = new Uint8Array(buffer);
  return a.length === bytes.length && a.every((v, i) => v === bytes[i]);
};

const ensureSubscription = async () => {
  const registration = await navigator.serviceWorker.ready;
  const expectedKey = base64UrlToBytes(VAPID_PUBLIC_KEY);
  let sub = await registration.pushManager.getSubscription();

  if (sub && !sameKey(sub.options.applicationServerKey, expectedKey)) {
    console.log('Veralteter Schlüssel – Abonnement wird erneuert');
    await sub.unsubscribe();
    sub = null;
  }

  sub ??= await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: expectedKey,
  });
  return sub;
};

ensureSubscription().then((s) => console.log('Endpoint:', s.endpoint));
Endpoint: https://fcm.googleapis.com/fcm/send/...

Schlüssel als Base64url an den Server melden

const bufferToBase64Url = (buf) =>
  btoa(String.fromCharCode(...new Uint8Array(buf)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

const registration = await navigator.serviceWorker.ready;
const sub = await registration.pushManager.getSubscription();

if (sub?.options.applicationServerKey) {
  await fetch('/api/push/check', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      endpoint: sub.endpoint,
      serverKey: bufferToBase64Url(sub.options.applicationServerKey),
    }),
  });
}

// Wichtig · Fallstricke

  • applicationServerKey ist immer ein ArrayBuffer. Ein direkter Vergleich mit === gegen einen String oder ein Uint8Array ergibt daher immer false. Vergleiche die Werte deshalb Byte für Byte.
  • Die Eigenschaft ist schreibgeschützt. Um die Optionen zu ändern, kündigst du das Abonnement mit unsubscribe() und legst es mit subscribe() neu an.
  • options ist nicht Teil der Ausgabe von PushSubscription.toJSON() und wird dadurch nicht automatisch an den Server übertragen.
  • Chrome und Safari verlangen userVisibleOnly: true. Der Wert ist in der Praxis also fast immer true.
  • Die Push-API funktioniert nur in sicheren Kontexten (HTTPS) und mit einem registrierten Service Worker. Safari unterstützt sie ab Version 16 (macOS) bzw. 16.4 (iOS, nur bei zum Home-Bildschirm hinzugefügten Web-Apps). Ältere Firefox-Versionen vor 75 kennen options noch nicht. Prüfe deshalb vor dem Zugriff, ob die Eigenschaft vorhanden ist.