Résumé

  • Une position d’octet décrit un emplacement, jamais l’identité de la version à laquelle cet emplacement appartient.
  • Avec Range et If-Range, une correspondance forte maintient la demande partielle ; une divergence fait ignorer la plage et renvoie la représentation courante complète.
  • Ce branchement économise une deuxième requête sans prétendre garantir la prise en charge des plages, la réception, l’assemblage, l’intégrité ou l’identité de l’origine.

Reprendre n’était pas simplement continuer

Un logiciel a conservé les deux premiers mégaoctets d’une archive lorsque la connexion s’est interrompue. Quelques minutes plus tard, il demande les octets suivants. Si l’archive n’a pas bougé, cette économie est évidente. Si une nouvelle archive a remplacé l’ancienne, joindre la nouvelle fin à l’ancien début fabrique un objet hybride. Toutes les réponses peuvent être correctement encadrées et pourtant le résultat n’a jamais existé chez l’origine.

La difficulté se situe donc au-dessus de la reconnexion. Le transport sait qu’un flux s’est arrêté ; il ne sait pas si une nouvelle requête HTTP sélectionne encore les mêmes octets. Range peut nommer l’intervalle manquant, mais une coordonnée n’est pas un numéro de version. Il fallait joindre à la position une preuve limitée de continuité.

En 1997, RFC 2068 inscrit If-Range dans la première spécification HTTP/1.1 normalisée. Le texte part d’une comparaison avec un GET conditionnel ordinaire. Si la représentation a changé, une précondition comme If-Match échoue, puis le client doit effectuer une seconde requête pour obtenir le corps complet. If-Range supprime ce détour : si l’entité est inchangée, envoyer les parties manquantes ; sinon envoyer la nouvelle entité en entier.

La formulation survit dans RFC 2616 en 1999. Le document associe la correspondance de l’étiquette à 206 Partial Content et sa divergence à 200 OK avec l’entité complète. Ce choix est essentiel. Une condition fausse n’interdit pas la lecture. Elle signifie seulement que l’ancienne copie ne mérite plus d’être complétée.

Une condition choisissait la forme de la réponse

Le client pouvait envoyer, par exemple :

Range: bytes=2000000-
If-Range: "edition-42"

La demande possède deux issues utiles. Si "edition-42" désigne toujours fortement la représentation sélectionnée, le serveur traite la plage. Sinon, il oublie la plage et répond comme à un GET normal avec la représentation courante. Le client doit alors remplacer sa copie partielle au lieu de lui ajouter la réponse.

Ce n’est ni la logique de 304 ni celle de 412. If-None-Match permet de ne pas transférer une représentation que le client possède déjà. If-Match peut empêcher une opération quand l’état préalable n’est plus celui attendu. If-Range, lui, annonce d’avance que le contenu complet actuel reste une bonne réponse. La divergence modifie le volume envoyé ; elle ne transforme pas la requête en refus.

RFC 7233 isole en 2014 les requêtes de plage et précise la discipline. If-Range ne doit pas être produit sans Range. Il est ignoré si la plage manque ou si la ressource ne prend pas en charge cette opération. En cas de correspondance, le serveur devrait traiter Range ; en cas de divergence, il doit l’ignorer. Le raccourci évite une requête supplémentaire, mais il ne commande pas à l’origine de fournir une plage qu’elle ne sait pas servir.

La consolidation actuelle, RFC 9110, rend le branchement encore plus lisible : pour GET avec Range et If-Range, une condition vraie et une plage applicable donnent 206 ; autrement, la plage est ignorée et la réponse normale est 200. Les erreurs, redirections et contrôles ordinaires restent prioritaires. Le champ n’est pas un laissez-passer autour de la sémantique HTTP.

Les fragments exigeaient une égalité forte

HTTP distingue les validateurs forts et faibles parce que « suffisamment semblable pour être réutilisé » n’équivaut pas à « identique octet par octet ». Deux rendus peuvent conserver le même sens tout en ayant des espaces, un encodage ou une sérialisation différents. Une validation faible peut suffire pour éviter de recharger une page. Elle ne suffit pas pour poser le second morceau exactement derrière le premier.

RFC 7232 réserve les validateurs forts aux comparaisons où toute modification observable des données compte, notamment les plages partielles. Un client ne peut donc pas envoyer une étiquette faible dans If-Range. Il ne peut utiliser une date Last-Modified que s’il ne dispose pas d’étiquette et que cette date remplit elle-même les conditions d’un validateur fort.

Cette prudence sur les dates protège contre une illusion courante. Une horloge peut être moins précise que le rythme des modifications. Deux versions peuvent partager la même seconde. La comparaison If-Range avec une date est exacte ; elle n’adopte pas la relation « antérieure ou égale » de If-Unmodified-Since. Si la date n’identifie pas suffisamment les octets, la condition doit être considérée comme fausse.

Une ETag reste pourtant une valeur opaque. Elle n’est pas nécessairement un condensat cryptographique. Son caractère fort exprime un engagement de non-réutilisation pour des données observables différentes de cette ressource. Il ne prouve ni l’auteur, ni la validité du contenu, ni l’équivalence d’une autre URL. RFC 2616 signalait déjà qu’une même étiquette utilisée sur plusieurs URI n’établissait aucune identité entre leurs entités.

La correspondance n’ordonnait pas un 206

Après une comparaison positive, le serveur doit encore savoir si l’unité de plage est comprise, si la syntaxe est valide et si l’intervalle rencontre la longueur courante. Une plage valable et satisfaisable produit normalement 206 Partial Content. Pour une seule partie, Content-Range place les octets dans la représentation complète. Plusieurs parties emploient multipart/byteranges. Une plage hors de l’étendue courante peut mener à 416 Range Not Satisfiable.

Le statut et Content-Range décrivent la réponse obtenue ; ils ne remplacent pas le validateur. La mention bytes 2000000-2999999/5000000 situe un morceau, mais ne certifie pas que le morceau conservé précédemment appartient à la même version. Inversement, une ETag correspondante ne prouve pas que le client a reçu, écrit et relu tous les octets.

La politique d’échec révèle le risque privilégié par HTTP. Une divergence, même déclenchée trop souvent, gaspille du réseau en renvoyant le tout. Une fausse correspondance peut engendrer silencieusement un fichier composé de deux histoires. Le protocole préfère une retransmission visible à une continuité inventée.

Le cache devenait gardien des pièces

Un cache peut stocker une réponse 200 incomplète, une réponse 206 ou plusieurs intervalles. Dès qu’il les réunit, il exerce une fonction de garde. RFC 7234 n’autorise le stockage partiel que si le cache comprend Range et Content-Range. Il n’autorise la combinaison de plusieurs plages que si elles partagent le même validateur fort.

La couverture arithmétique ne suffit pas. Un préfixe de lundi, un milieu de mardi et une fin de mercredi peuvent occuper toutes les positions sans appartenir au même objet. Le cache doit conserver la version commune et mettre à jour les métadonnées selon les règles de combinaison. Il ne doit jamais présenter une réponse partielle comme complète simplement parce que sa longueur paraît plausible.

RFC 9111 maintient aujourd’hui cette frontière. Un cache peut compléter une réponse avec des demandes ultérieures, mais ne peut la réutiliser comme totalité avant que la totalité soit réellement constituée. Le code 206 doit rester visible lorsque la réponse est partielle. If-Range fournit une condition de branchement ; la garde, la réutilisation et la complétude restent des responsabilités locales.

L’ensemble forme un dossier de preuve réparti. La cible et les paramètres de négociation identifient la représentation sélectionnée. Range nomme l’intervalle. If-Range transporte le validateur associé aux octets conservés. Le serveur compare son état courant. Le statut et Content-Range expliquent ce qu’il a envoyé. Seul le journal du client ou du cache peut démontrer l’assemblage final.

Une économie sans registre central des versions

If-Range aurait pu être conçu comme un verrou ou un service de session durable. Il a choisi une voie plus petite. L’origine crée le validateur ; le client le garde avec ses octets ; le serveur compare ; le cache répond de ses pièces. Aucun registre mondial ne distribue les identités de fichier et aucune interruption n’oblige l’origine à geler la ressource.

Le champ partagé répond à une seule question : la demande partielle peut-elle encore compléter cette représentation ? Une réponse négative retire le privilège économique, pas le droit d’obtenir le contenu courant. Cette limitation conserve l’autorité des participants tout en leur donnant une règle interopérable.

Les RFC décrivent cette règle, pas les pratiques d’un produit actuel. Elles ne prouvent ni la force d’une ETag en production, ni la conservation correcte par un intermédiaire, ni le succès d’un téléchargement. Une enquête réelle exige les requêtes, les entrées de négociation, l’historique des validateurs, les réponses, les intervalles et les empreintes du résultat assemblé.