Accès asynchrone aux cookies HTTP

Victor Costan

Qu'est-ce que l'API Cookie Store ?

L'API Cookie Store expose les cookies HTTP aux service workers et offre une alternative asynchrone à document.cookie. Cette API facilite les opérations suivantes:

  • Évitez les à-coups sur le thread principal en accédant aux cookies de manière asynchrone.
  • Évitez d'interroger les cookies, car vous pouvez constater des modifications apportées aux cookies.
  • Accéder aux cookies des service workers

Lire l'explication

État actuel

Step État
1. Créer une vidéo explicative Fin
2. Créer une ébauche initiale de spécification Fin
**3. Recueillez des commentaires et modifiez les spécifications** **En cours**
4. Phase d'évaluation En pause
5. Lancement Non démarrée

Comment utiliser le magasin de cookies asynchrones ?

Activer la phase d'évaluation

Pour l'essayer en local, vous pouvez activer l'API via la ligne de commande:

chrome --enable-blink-features=CookieStore

La transmission de cet indicateur sur la ligne de commande active l'API de manière globale dans Chrome pour la session en cours.

Vous pouvez également activer l'option #enable-experimental-web-platform-features dans chrome://flags.

Vous n'avez (probablement) pas besoin de cookies

Avant de nous intéresser à la nouvelle API, je voudrais indiquer que les cookies sont toujours la pire primitive de stockage côté client de la plate-forme Web et qu'ils doivent toujours être utilisés en dernier recours. Ce n'est pas un hasard. Les cookies étaient le premier mécanisme de stockage côté client sur le Web, et nous avons beaucoup appris depuis.

Voici les principales raisons pour lesquelles vous évitez les cookies:

  • Les cookies importent votre schéma de stockage dans votre API backend. Chaque requête HTTP contient un instantané du fichier cookie jar. Cela permet aux ingénieurs backend d'introduire facilement des dépendances sur le format de cookie actuel. Une fois que cela se produit, votre interface ne peut plus modifier son schéma de stockage sans déployer une modification correspondante sur le backend.

  • Les cookies ont un modèle de sécurité complexe. Les fonctionnalités de la plate-forme Web moderne suivent les mêmes règles relatives à l'origine, ce qui signifie que chaque application dispose de son propre bac à sable et est complètement indépendante des autres applications que l'utilisateur pourrait exécuter. Les champs d'application des cookies permettent d'obtenir un scénario de sécurité beaucoup plus complexe. Ils s'efforcent simplement de résumer la taille de cet article, qui doublerait la taille de cet article.

  • Les cookies ont des coûts de performance élevés. Les navigateurs doivent inclure un instantané de vos cookies dans chaque requête HTTP. Toutes les modifications apportées aux cookies doivent donc être propagées sur les piles de stockage et réseau. Dans les navigateurs récents, la mise en œuvre de magasins de cookies est hautement optimisée, mais nous ne serons jamais en mesure d'obtenir des cookies aussi efficaces que les autres mécanismes de stockage, qui n'ont pas besoin de communiquer avec la pile réseau.

Pour toutes les raisons ci-dessus, les applications Web modernes doivent éviter les cookies et stocker un identifiant de session dans IndexedDB, et ajouter explicitement l'identifiant à l'en-tête ou au corps de requêtes HTTP spécifiques via l'API fetch.

Ceci étant dit, vous lisez toujours cet article parce que vous avez une bonne raison d'utiliser des cookies...

L'API document.cookie éprouvée est une source d'à-coups assez garantie pour votre application. Par exemple, lorsque vous utilisez le getter document.cookie, le navigateur doit arrêter d'exécuter JavaScript jusqu'à ce qu'il dispose des informations de cookie que vous avez demandées. Cela peut prendre un saut de processus ou une lecture de disque, ce qui entraîne des à-coups dans l'interface utilisateur.

Une solution simple à ce problème consiste à passer du getter document.cookie à l'API Cookie Store asynchrone.

await cookieStore.get('session_id');

// {
//   domain: "example.com",
//   expires: 1593745721000,
//   name: "session_id",
//   path: "/",
//   sameSite: "unrestricted",
//   secure: true,
//   value: "yxlgco2xtqb.ly25tv3tkb8"
// }

Le setter document.cookie peut être remplacé de la même manière. N'oubliez pas que la modification ne sera appliquée qu'une fois la promesse renvoyée par cookieStore.set résolue.

await cookieStore.set({name: 'opt_out', value: '1'});

// undefined

Observer, ne pas interroger

Une application populaire permettant d'accéder aux cookies à partir de JavaScript détecte la déconnexion de l'utilisateur et met à jour l'interface utilisateur. Pour ce faire, vous interrogez actuellement document.cookie, qui introduit des à-coups et a un impact négatif sur l'autonomie de la batterie.

L'API Cookie Store propose une autre méthode qui ne nécessite pas d'interrogation pour observer les modifications apportées aux cookies.

cookieStore.addEventListener('change', event => {
  for (const cookie of event.changed) {
    if (cookie.name === 'session_id') sessionCookieChanged(cookie.value);
  }
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') sessionCookieChanged(null);
  }
});

Bienvenue aux service workers

En raison de la conception synchrone, l'API document.cookie n'a pas été mise à la disposition des service workers. L'API Cookie Store est asynchrone et est donc autorisée dans les service workers.

L'interaction avec les cookies fonctionne de la même manière dans les contextes de document et dans les service workers.

// Works in documents and service workers.
async function logOut() {
  await cookieStore.delete('session_id');
}

Cependant, l'observation des modifications des cookies est un peu différente chez les service workers. Le déclenchement d'un service worker peut s'avérer assez coûteux. Nous devons donc décrire explicitement les modifications de cookies qui l'intéressent.

Dans l'exemple ci-dessous, une application qui utilise IndexedDB pour mettre en cache les données utilisateur surveille les modifications apportées au cookie de session et supprime les données mises en cache lorsque l'utilisateur se déconnecte.

// Specify the cookie changes we're interested in during the install event.
self.addEventListener('install', event => {
  event.waitUntil(cookieStore.subscribeToChanges([{name: 'session_id'}]));
});

// Delete cached data when the user logs out.
self.addEventListener('cookiechange', event => {
  for (const cookie of event.deleted) {
    if (cookie.name === 'session_id') {
      indexedDB.deleteDatabase('user_cache');
      break;
    }
  }
});

Bonnes pratiques

Bientôt disponible.

Commentaires

Si vous essayez cette API, n'hésitez pas à nous donner votre avis ! Veuillez envoyer vos commentaires sur la forme de l'API au dépôt de spécifications et signaler les bugs d'implémentation au composant Blink Blink>Storage>CookiesAPI.

Les mesures des performances et les cas d'utilisation autres que ceux décrits dans l'explication nous intéressent tout particulièrement.

Ressources supplémentaires