13 novembre 2022

API Fetch

Jusqu’à prĂ©sent, nous en savons pas mal sur fetch.

Voyons le reste de l’API, pour couvrir toutes ses capacitĂ©s.

Veuillez noter :

Remarque: la plupart de ces options sont rarement utilisées. Vous pouvez ignorer ce chapitre et continuer à utiliser fetch correctement.

Pourtant, il est bon de savoir ce que fetch peut faire, donc si le besoin s’en fait sentir, vous pouvez revenir et lire les dĂ©tails.

Voici la liste complÚte de toutes les options possibles de fetch avec leurs valeurs par défaut (alternatives dans les commentaires) :

let promise = fetch(url, {
  method: "GET", // POST, PUT, DELETE, etc.
  headers: {
    // la valeur de l'en-tĂȘte du type de contenu est gĂ©nĂ©ralement dĂ©finie automatiquement
    // selon la requĂȘte du body
    "Content-Type": "text/plain;charset=UTF-8"
  },
  body: undefined, // string, FormData, Blob, BufferSource, ou URLSearchParams
  referrer: "about:client", // ou "" to send no Referer header,
  // or an url from the current origin
  referrerPolicy: "strict-origin-when-cross-origin", // no-referrer-when-downgrade, no-referrer, origin, same-origin...
  mode: "cors", // same-origin, no-cors
  credentials: "same-origin", // omit, include
  cache: "default", // no-store, reload, no-cache, force-cache, or only-if-cached
  redirect: "follow", // manual, error
  integrity: "", // un hash, comme "sha256-abcdef1234567890"
  keepalive: false, // true
  signal: undefined, // AbortController pour annuler la requĂȘte
  window: window // null
});

Une liste impressionnante, non ?

Nous avons entiĂšrement couvert method, headers et body dans le chapitre Fetch.

L’option signal est couverte dans Fetch: Abort.

Explorons maintenant le reste des capacités.

referrer, referrerPolicy

Ces options rĂ©gissent la façon dont fetch dĂ©finit l’en-tĂȘte HTTP Referer.

Habituellement, cet en-tĂȘte est dĂ©fini automatiquement et contient l’url de la page Ă  l’origine de la requĂȘte. Dans la plupart des scĂ©narios, ce n’est pas important du tout, parfois, pour des raisons de sĂ©curitĂ©, il est logique de le supprimer ou de le raccourcir.

L’option referer permet de dĂ©finir n’importe quel Referer dans l’origine actuelle) ou de le supprimer.

Pour n’envoyer aucun referer, dĂ©finissez une chaĂźne de caractĂšres vide :

fetch('/page', {
  referrer: "" // pas de header Referer
});

Pour dĂ©finir une autre URL dans l’origine actuelle :

fetch('/page', {
  // en supposant que nous sommes sur https://javascript.info
  // nous pouvons dĂ©finir n'importe quel en-tĂȘte Referer, mais uniquement dans l'origine actuelle
  referrer: "https://javascript.info/anotherpage"
});

L’option referrerPolicy Ă©tablit des rĂšgles gĂ©nĂ©rales pour Referer.

Les requĂȘtes sont divisĂ©es en 3 types :

  1. RequĂȘte Ă  la mĂȘme origine.
  2. RequĂȘte Ă  une autre origine.
  3. RequĂȘte de HTTPS Ă  HTTP (du protocole sĂ»r au protocole non sĂ©curisĂ©).

Contrairement Ă  l’option referrer qui permet de dĂ©finir la valeur exacte de Referer, referrerPolicy indique les rĂšgles gĂ©nĂ©rales du navigateur pour chaque type de requĂȘte.

Les valeurs possibles sont décrites dans la spécification Referrer Policy:

  • "strict-origin-when-cross-origin" – la valeur par dĂ©faut : pour la mĂȘme origine, envoie le Referer complet, pour l’origine croisĂ©e, envoie uniquement l’origine, Ă  moins qu’il ne s’agisse d’une requĂȘte HTTPS→HTTP , puis n’envoie rien.
  • "no-referrer-when-downgrade" – le Referer complet est toujours envoyĂ©, sauf si nous envoyons une requĂȘte de HTTPS Ă  HTTP (vers le protocole le moins sĂ©curisĂ©).
  • "no-referrer" – n’envoie jamais le Referer.
  • "origine" – n’envoie que l’origine dans le Referer, pas l’URL complĂšte de la page, par ex. uniquement http://site.com au lieu de http://site.com/path.
  • "origin-when-cross-origin" – envoie le Referer complet Ă  la mĂȘme origine, mais uniquement la partie d’origine pour les requĂȘtes cross-origin (comme ci-dessus).
  • "same-origin" – envoie le Referer complet Ă  la mĂȘme origine, mais pas de Referer pour les requĂȘtes cross-origin.
  • "strict-origin" – envoie uniquement l’origine, pas le Referer pour les requĂȘtes HTTPS→HTTP.
  • "unsafe-url" – envoie toujours l’url complĂšte dans Referer, mĂȘme pour les requĂȘtes HTTPS→HTTP.

Voici un tableau avec toutes les combinaisons :

Valeur Pour la mĂȘme origine Pour une autre origine HTTPS→HTTP
"no-referrer" - - -
"no-referrer-when-downgrade" full full -
"origin" origin origin origin
"origin-when-cross-origin" full origin origin
"same-origin" full - -
"strict-origin" origin origin -
"strict-origin-when-cross-origin" or "" (default) full origin -
"unsafe-url" full full full

Disons que nous avons une zone d’administration avec une structure d’URL qui ne devrait pas ĂȘtre connue de l’extĂ©rieur du site.

Si nous envoyons un fetch, alors par dĂ©faut, il envoie toujours l’en-tĂȘte Referer avec l’url complĂšte de notre page (sauf lorsque nous demandons de HTTPS Ă  HTTP, alors pas de Referer).

Par exemple : Referer: https://javascript.info/admin/secret/paths.

Si nous souhaitons que d’autres sites Web connaissent uniquement la partie origin, pas le chemin URL, nous pouvons dĂ©finir l’option :

fetch('https://another.com/page', {
  // ...
  referrerPolicy: "origin-when-cross-origin" // Referer: https://javascript.info
});

Nous pouvons le mettre Ă  tous les appels fetch, peut-ĂȘtre l’intĂ©grer dans la bibliothĂšque JavaScript de notre projet qui fait toutes les requĂȘtes et utilise fetch Ă  l’intĂ©rieur.

Sa seule diffĂ©rence par rapport au comportement par dĂ©faut est que pour les requĂȘtes vers une autre origine, fetch envoie uniquement la partie origine de l’URL (par exemple https://javascript.info, sans le chemin). Pour les requĂȘtes Ă  notre origine, nous obtenons toujours le Referer complet (peut-ĂȘtre utile Ă  des fins de dĂ©bogage).

La Referrer policy n’est pas seulement pour fetch

La Referrer policy, dĂ©crite dans la spĂ©cification, n’est pas seulement pour fetch, mais plus globale.

Plus particuliĂšrement, il est possible de dĂ©finir la politique par dĂ©faut pour toute la page en utilisant l’en-tĂȘte HTTP Referrer-Policy, ou par lien, avec <a rel="noreferrer">.

mode

L’option mode est un garde-fou qui empĂȘche les requĂȘtes cross-origin occasionnelles :

  • "cors" – par dĂ©faut, les requĂȘtes cross-origin sont autorisĂ©es, comme dĂ©crit dans Fetch: RequĂȘtes Cross-Origin,
  • "same-origin" – les requĂȘtes cross-origin requests sont interdites,
  • "no-cors" – seules les requĂȘtes cross-origin sĂ©curisĂ©es sont autorisĂ©es.

Cette option peut ĂȘtre utile lorsque l’URL de fetch provient d’un tiers, et nous voulons un “interrupteur de mise hors tension” pour limiter les capacitĂ©s de cross-origin.

credentials

L’option credentials spĂ©cifie si fetch doit envoyer des cookies et des en-tĂȘtes d’autorisation HTTP avec la requĂȘte.

  • "same-origin" – par dĂ©faut, n’envoyez pas de requĂȘtes cross-origin,
  • "include" – toujours envoyer, nĂ©cessite Accept-Control-Allow-Credentials du serveur cross-origin pour que JavaScript accĂšde Ă  la rĂ©ponse, qui a Ă©tĂ© traitĂ©e dans le chapitre Fetch: RequĂȘtes Cross-Origin,
  • "omit" – ne jamais envoyer, mĂȘme pour des requĂȘtes cross-origin.

cache

Par dĂ©faut, les requĂȘtes fetch utilisent la mise en cache HTTP standard. Autrement dit, il honore les en-tĂȘtes Expires et Cache-Control, envoie If-Modified-Since, et ainsi de suite. Tout comme les requĂȘtes HTTP rĂ©guliĂšres.

Les options cache permettent d’ignorer le cache HTTP ou d’affiner son utilisation :

  • "default" – fetch utilise des rĂšgles et des en-tĂȘtes de cache HTTP standard,
  • "no-store" – ignore totalement le cache HTTP, ce mode devient la valeur par dĂ©faut si nous dĂ©finissons un en-tĂȘte If-Modified-Since, If-None-Match, If-Unmodified-Since, If-Match, ou If-Range,
  • "reload" – ne prenez pas le rĂ©sultat du cache HTTP (le cas Ă©chĂ©ant), mais remplissez le cache avec la rĂ©ponse (si les en-tĂȘtes de rĂ©ponse le permettent),
  • "no-cache" – crĂ©er une requĂȘte conditionnelle s’il y a une rĂ©ponse mise en cache, et sinon une requĂȘte normale. Remplissez le cache HTTP avec la rĂ©ponse,
  • "force-cache" – utilise une rĂ©ponse du cache HTTP, mĂȘme si elle est pĂ©rimĂ©e. S’il n’y a pas de rĂ©ponse dans le cache HTTP, fait une requĂȘte HTTP rĂ©guliĂšre, se comporte normalement,
  • "only-if-cached" – utilise une rĂ©ponse du cache HTTP, mĂȘme si elle est pĂ©rimĂ©e. S’il n’y a pas de rĂ©ponse dans le cache HTTP, alors erreur. Fonctionne uniquement lorsque le mode est sur "same-origin".

redirect

Normalement, fetch suit de maniĂšre transparente les redirections HTTP, comme 301, 302 etc.

L’option redirect permet de changer cela :

  • "follow" – par dĂ©faut, suit les redirections HTTP,
  • "error" – erreur en cas de redirection HTTP,
  • "manual" – permet de traiter manuellement les redirections HTTP. En cas de redirection, nous obtiendrons un objet de rĂ©ponse spĂ©cial, avec response.hype="opaqueredirect" et un statut zĂ©ro/vide ainsi que la plupart des autres propriĂ©tĂ©s.

integrity

L’option intĂ©gritĂ© permet de vĂ©rifier si la rĂ©ponse correspond Ă  la somme de contrĂŽle connue Ă  l’avance.

Comme dĂ©crit dans la spĂ©cification, les fonctions de hachage prises en charge sont SHA-256, SHA-384 et SHA-512, il peut y en avoir d’autres en fonction du navigateur.

Par exemple, nous tĂ©lĂ©chargeons un fichier et nous savons que sa somme de contrĂŽle SHA-256 est “abcdef” (une vraie somme de contrĂŽle est plus longue, bien sĂ»r).

Nous pouvons le mettre dans l’option integrity, comme ceci :

fetch('http://site.com/file', {
  integrity: 'sha256-abcdef'
});

Ensuite, fetch calculera SHA-256 seul et le comparera avec notre chaßne de caractÚres. En cas de non-concordance, une erreur est déclenchée.

keepalive

L’option keepalive indique que la demande peut “survivre” Ă  la page Web qui l’a initiĂ©e.

Par exemple, nous recueillons des statistiques sur la façon dont le visiteur actuel utilise notre page (clics de souris, fragments de page qu’il consulte), pour analyser et amĂ©liorer l’expĂ©rience utilisateur.

Lorsque le visiteur quitte notre page – nous aimerions enregistrer les donnĂ©es sur notre serveur.

Nous pouvons utiliser l’évĂ©nement window.onunload pour cela :

window.onunload = function() {
  fetch('/analytics', {
    method: 'POST',
    body: "statistics",
    keepalive: true
  });
};

Normalement, lorsqu’un document est dĂ©chargĂ©, toutes les requĂȘtes rĂ©seau associĂ©es sont abandonnĂ©es. Mais l’option keepalive indique au navigateur d’exĂ©cuter la requĂȘte en arriĂšre-plan, mĂȘme aprĂšs avoir quittĂ© la page. Cette option est donc essentielle Ă  la rĂ©ussite de notre demande.

Elle a quelques limitations :

  • Nous ne pouvons pas envoyer des mĂ©gaoctets : la limite de corps pour les requĂȘtes keepalive est de 64kb.
    • Si nous avons besoin de rassembler beaucoup de statistiques sur la visite, nous devons les envoyer rĂ©guliĂšrement par paquets, afin qu’il ne reste plus grand-chose pour la derniĂšre requĂȘte onunload.
    • Cette limite s’applique Ă  toutes les demandes keepalive ensemble. En d’autres termes, nous pouvons effectuer plusieurs requĂȘtes keepalive en parallĂšle, mais la somme de leurs longueurs de corps ne doit pas dĂ©passer 64 Kb.
  • Nous ne pouvons pas gĂ©rer la rĂ©ponse du serveur si le document est dĂ©chargĂ©. Donc, dans notre exemple, fetch rĂ©ussira grĂące Ă  keepalive, mais les fonctions suivantes ne fonctionneront pas.
    • Dans la plupart des cas, comme l’envoi de statistiques, ce n’est pas un problĂšme, car le serveur accepte simplement les donnĂ©es et envoie gĂ©nĂ©ralement une rĂ©ponse vide Ă  de telles demandes.
Carte du tutoriel

Commentaires

lire ceci avant de commenter

  • Si vous avez des amĂ©liorations Ă  suggĂ©rer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
  • Si vous ne comprenez pas quelque chose dans l'article, merci de prĂ©ciser.
  • Pour insĂ©rer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes – enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen
)