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 services workers et propose une alternative asynchrone à document.cookie. L'API permet de:

  • Évitez les à-coups sur le thread principal en accédant aux cookies de manière asynchrone.
  • Évitez d'interroger les cookies, car les modifications apportées aux cookies peuvent être observées.
  • Accéder aux cookies à partir de service workers.

Lire la vidéo explicative

État actuel

Étape État
1. Créer un message d'explication Fin
2. Créer une première ébauche de la spécification Fin
**3. Recueillir des commentaires et itérer sur les spécifications** **En cours**
4. Essai Origin En pause
5. Lancer Non démarrée

Comment utiliser le cookie store asynchrone ?

Activer l'essai de l'origine

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

chrome --enable-blink-features=CookieStore

Transmettre cet indicateur sur la ligne de commande active l'API globalement 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 vous présenter la nouvelle API, je tiens à préciser que les cookies restent 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 ont été le premier mécanisme de stockage côté client du Web, et nous avons beaucoup appris depuis.

Voici les principales raisons d'éviter les cookies:

  • Les cookies importent votre schéma de stockage dans votre API backend. Chaque requête HTTP contient un instantané du fichier cookie. Les ingénieurs backend peuvent ainsi facilement introduire des dépendances sur le format de cookie actuel. Une fois cela fait, votre front-end ne peut plus modifier son schéma de stockage sans déployer une modification correspondante dans le backend.

  • Les cookies ont un modèle de sécurité complexe. Les fonctionnalités des plates-formes Web modernes suivent la même règle d'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 peut exécuter. Les champs d'application des cookies constituent un sujet de sécurité beaucoup plus complexe, et la simple tentative de le résumer doublerait la taille de cet article.

  • Les cookies ont un coût élevé en termes de performances. Les navigateurs doivent inclure un instantané de vos cookies dans chaque requête HTTP. Par conséquent, chaque modification apportée aux cookies doit être propagée dans les piles de stockage et de réseau. Les navigateurs modernes disposent d'implémentations de stockage de cookies hautement optimisées, mais nous ne pourrons jamais rendre les 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 plutôt 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.

Cela dit, vous lisez toujours cet article, car vous avez une bonne raison d'utiliser des cookies.

L'ancienne API document.cookie est une source de saccades quasi garantie pour votre application. Par exemple, chaque fois que vous utilisez le getter document.cookie, le navigateur doit arrêter l'exécution de JavaScript jusqu'à ce qu'il dispose des informations sur les cookies que vous avez demandées. Cela peut nécessiter un saut de processus ou une lecture de disque, ce qui entraînera des à-coups dans l'interface utilisateur.

Pour résoudre ce problème, il suffit de 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 n'est garantie que lorsqu'elle est appliquée après la résolution de la promesse renvoyée par cookieStore.set.

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

// undefined

Observer, pas sonder

Une application populaire pour accéder aux cookies à partir de JavaScript consiste à détecter quand l'utilisateur se déconnecte et à mettre à jour l'UI. Cela est actuellement effectué par le sondage 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 d'observation des modifications des cookies, qui ne nécessite pas de sondage.

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 workers de service. L'API Cookie Store est asynchrone et est donc autorisée dans les workers de service.

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

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

Toutefois, l'observation des modifications apportées aux cookies est légèrement différente dans les services workers. Le réveil d'un service worker peut être assez coûteux. Nous devons donc décrire explicitement les modifications de cookies qui intéressent le worker.

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 faire part de vos commentaires. 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.

Nous sommes particulièrement intéressés par les mesures de performances et les cas d'utilisation au-delà de ceux décrits dans la présentation.

Ressources supplémentaires