Résumé

  • RFC 9659 impose aux décodeurs HTTP zstd de prendre en charge les fenêtres jusqu’à 8 Mo inclus et interdit aux encodeurs de produire des trames qui exigent davantage.
  • La conformité de l’origine ne prouve pas qu’un CDN, un proxy ou une variante ancienne n’a pas remplacé ou recompressé les octets servis.
  • Une affirmation d’interopérabilité défendable relie la trame réelle à sa chaîne de transformation, sa clé de cache, la limite effective du destinataire et l’acceptation applicative.

L’équipe d’origine avait bien plafonné l’encodeur à 8 Mo. Son test de construction analysait les trames, sa configuration était versionnée et son échantillon passait dans plusieurs navigateurs. Pourtant, un intermédiaire autorisé à transformer les représentations pouvait décoder puis recomprimer la réponse avec ses propres valeurs. La réponse portait toujours Content-Encoding: zstd; la preuve attachée à l’origine ne décrivait plus les octets livrés.

Ce scénario explique pourquoi RFC 9659 doit être lu comme un contrat symétrique, non comme un certificat. Pour le codage de contenu HTTP zstd, le décodeur DOIT accepter une Window_Size allant jusqu’à 8 Mo inclus, et l’encodeur NE DOIT PAS créer une trame qui réclame plus de 8 Mo. Le document transforme la recommandation de RFC 8878 en exigence commune. Il ne désigne pas l’acteur qui a touché les octets en dernier.

Une frontière mémoire inscrite dans la trame

RFC 8878 décrit Zstandard et sa structure de trame. La fenêtre fixe la distance maximale des références vers des données déjà décodées et donc une partie de la mémoire que le destinataire doit conserver. Le format autorise une amplitude considérable, de 1 Ko à environ 3,75 To. Une fenêtre plus grande peut améliorer le taux de compression, mais déplace un coût vers le décodeur.

RFC 8878 recommandait déjà 8 Mo pour l’usage HTTP, sans en faire une obligation. Cette souplesse permettait à un producteur d’optimiser au-delà de la capacité qu’un agent utilisateur limitait légitimement. RFC 9659 supprime cet espace d’interprétation pour zstd. Le texte canonique et la source XML montrent la modestie volontaire du changement : deux exigences, une limite, un registre mis à jour.

La notice du RFC Editor rappelle que le document, publié par l’IETF à titre informationnel, met à jour RFC 8878. La recherche d’errata et l’historique Datatracker permettent de rattacher une politique locale au texte public précis, plutôt qu’à une mémoire informelle de la règle.

Le nom du codage ne décrit pas la trame

RFC 9110 définit le rôle des codages de contenu. Accept-Encoding exprime ce que le destinataire annonce accepter; Content-Encoding décrit la transformation appliquée à la représentation choisie. Aucun de ces champs ne transporte la valeur de fenêtre Zstandard. Un journal montrant zstd prouve une décision de négociation, pas le paramètre de la trame ni le succès du décodage.

Cette séparation est essentielle quand plusieurs acteurs transforment le contenu. L’origine peut créer une trame conforme. Un proxy peut la décompresser pour inspection, puis la recomprimer. Un edge peut fabriquer une variante spécifique. Un dispositif de sécurité peut remplacer la réponse. La chaîne HTTP reste syntaxiquement correcte tandis que la provenance de la fenêtre se déplace.

RFC 7694 traite aussi de l’annonce des codages acceptables, cette fois pour le contenu d’une requête. Là encore, une annonce de capacité n’est ni la description des octets précis ni leur reçu de traitement. Dans les deux sens, il faut conserver séparément l’offre, le choix, la trame et le résultat.

Le cache conserve des décisions que la configuration a oubliées

RFC 9111 place le cache dans la sémantique de livraison. Une variante zstd peut rester fraîche après la correction de l’encodeur. Un changement de clé peut créer deux populations d’objets. Une purge peut atteindre l’origine et quelques edges, mais manquer une classe régionale. Une réponse de repli peut polluer une variante si la séparation des représentations est imparfaite.

Il ne suffit donc pas de demander : « quelle est la limite de l’encodeur ? » Il faut demander : « quel objet a été servi ? » Le reçu utile contient le hash des octets, la génération de l’objet, la clé de variante, l’état de fraîcheur, l’acteur de transformation, l’analyse de l’en-tête de trame et la classe du destinataire. À défaut, des indicateurs verts peuvent être exacts tout en parlant d’objets différents.

Le registre IANA des codages HTTP décrit désormais zstd comme un flux Zstandard dont la Window_Size ne dépasse pas 8 Mo. Le registre fixe le sens partagé du jeton. Il n’empêche pas un intermédiaire mal configuré de produire des octets qui contredisent ce sens. La coordination publique et la preuve de production sont deux couches distinctes.

« Le décodeur le permet » n’est pas « le processus l’a décodé »

La règle côté décodeur est indispensable. Elle garantit qu’un destinataire qui annonce le codage n’abaisse pas arbitrairement la frontière commune en dessous de 8 Mo. Mais une bibliothèque capable de 8 Mo peut être intégrée dans un processus avec une politique mémoire plus stricte. L’allocation peut échouer sous pression. Le décodage peut réussir et l’analyse applicative échouer ensuite. Un délai peut interrompre l’opération avant son résultat.

Une matrice sérieuse distingue donc la capacité de la bibliothèque, la limite effective du processus et le résultat de la représentation observée. Elle classe aussi les échecs : fenêtre supérieure à 8 Mo, flux tronqué, corruption, codage non pris en charge, ressource insuffisante, erreur applicative. RFC 9659 précise qu’un décodeur peut rencontrer une trame surdimensionnée non conforme et échouer; l’exigence de 8 Mo n’est pas une obligation de mémoire illimitée.

Ne pas mélanger zstd et dcz

RFC 9842 définit plus tard le transport de dictionnaires de compression et le codage dcz. Son contrat de fenêtre peut dépendre de la taille du dictionnaire et monter jusqu’à 128 Mo. Cette règle concerne un autre codage et une autre négociation. Elle ne relève pas le plafond du zstd ordinaire défini par RFC 9659.

Le risque naît lorsque la même bibliothèque et le même panneau d’administration exposent un paramètre générique de fenêtre. Sans le jeton de codage, l’identité du dictionnaire et la provenance de trame, un test dcz peut être utilisé par erreur pour justifier zstd, ou inversement. L’abstraction logicielle n’annule pas la différence de contrat.

Construire la preuve de bout en bout

À l’origine, conserver la version de l’encodeur, sa configuration effective, le hash de l’objet et l’en-tête de trame. À chaque intermédiaire, conserver la décision de laisser passer, décompresser, recomprimer ou remplacer. Dans le cache, conserver clé, génération, fraîcheur et purge. Chez le destinataire, conserver version, budget effectif, fenêtre observée, résultat de décodage et erreur classée. Dans l’application, conserver l’acceptation finale.

L’échantillonnage suffit s’il est conçu autour des frontières : petites et grandes réponses, anciennes et nouvelles générations, régions, edges, clients contraints, retours en arrière et replis. Les alertes doivent viser une trame au-dessus de 8 Mo, une différence de hash sans transformation documentée, un objet ancien survivant à une modification de cap, ou une divergence entre négociations zstd et résultats applicatifs.

La Spécification initiale minimale de Heng Lu aide à garder la règle commune étroite : 8 Mo et une sémantique d’échec explicite, sans interdire les optimisations locales conformes. Les couches de réalité empêchent le jeton zstd d’emprunter l’autorité du décodage. La primauté du code exécuté donne le dernier mot à la trame réellement servie et au destinataire qui l’a réellement traitée.

RFC 9659 rend la frontière nette. La gouvernance doit empêcher qu’elle se dissolve au premier intermédiaire.

Sources