Résumé

  • Les bindings WebDAV permettent à plusieurs URI d’atteindre une même ressource. Quand cette ressource est une collection, un second binding expose les mêmes membres sous un autre préfixe et peut même former une boucle.
  • Dans un PROPFIND Depth: infinity conscient des bindings, une occurrence de la collection reçoit 200 et ses descendants sont énumérés. Les autres chemins restent visibles avec 208 Already Reported, mais leur sous-arbre n’est pas reproduit.
  • DAV:resource-id fournit l’identité stable qui relie les chemins. Le client doit conserver toutes les arêtes de binding tout en n’explorant chaque collection qu’une fois; si le client ne comprend pas 208, une boucle conduit à 508 plutôt qu’à une réponse tronquée qu’il prendrait pour complète.

Deux adresses ne fabriquaient pas deux objets

Une collection peut apparaître dans deux rayonnages d’un même catalogue. Les deux entrées ont une réalité: chacune possède son emplacement, son parent et son nom. Mais ouvrir l’une ou l’autre conduit au même ensemble de dossiers.

Une exploration naïve a alors deux mauvaises options. Elle peut suivre chaque chemin comme s’il désignait un objet nouveau et compter deux fois les mêmes descendants. Ou elle peut fusionner les chemins dès qu’elle reconnaît l’objet et effacer une relation légitime de l’espace de noms.

La difficulté devient critique lorsqu’un chemin ramène vers un ancêtre. Une structure finie produit alors une suite infinie d’URI sans créer une infinité de ressources.

208 introduit une séparation plus disciplinée: constater l’alias, prouver l’identité commune, puis renoncer seulement à la seconde descente.

Multi-Status avait déjà séparé enveloppe et détail

Le RFC 4918, publié en 2007, décrit l’état d’une collection WebDAV comme un ensemble de correspondances entre segments de chemin et ressources, auquel s’ajoutent les propriétés de la collection. Le nom d’un membre est donc une relation d’accès, pas la ressource elle-même.

PROPFIND permet d’interroger la cible seule, ses membres directs ou tous ses descendants au moyen des profondeurs 0, 1 et infinity. Pour une collection, le serveur rend un 207 Multi-Status contenant une liste plate d’éléments DAV:response. Chaque href identifie un chemin et chaque propstat porte le résultat relatif aux propriétés demandées.

Le statut extérieur ne résume pas les résultats intérieurs. Un 207 peut contenir plusieurs états et le destinataire doit lire le corps. Cette distinction prépare le terrain de 208: une réussite au niveau de la requête ne dit pas comment chaque occurrence a été traitée dans l’inventaire.

WebDAV reconnaissait déjà qu’une ressource pouvait avoir plusieurs URI. Il manquait encore au client un mécanisme explicite pour créer un nouveau chemin vers une ressource existante.

BIND ajoutait une arête, pas une copie

Le RFC 5842, document IETF Experimental d’avril 2010, définit BIND, UNBIND et REBIND. BIND associe un segment de chemin d’une collection à une ressource déjà présente. La nouvelle URI devient une voie d’accès ordinaire à cette ressource.

Le binding est nouveau; la ressource ne l’est pas. Deux collections peuvent contenir chacune une relation vers le même objet. Ces relations sont distinctes même lorsque segment et cible sont identiques.

L’intégrité du binding impose qu’une relation continue d’exister et continue de nommer la même ressource jusqu’à l’exécution d’une opération qui la supprime ou la modifie explicitement. Retirer un chemin ne doit pas casser un autre chemin ni provoquer la récupération de la ressource tant qu’un binding subsiste.

Cette règle empêche l’optimisation de parcours de devenir une théorie de propriété. L’alias ne possède pas l’objet, mais il ne peut pas non plus être jeté comme un doublon de présentation.

Une collection liée projetait tous ses descendants

Créer un binding vers une ressource feuille ajoute une URI. Créer un binding vers une collection rend aussi les descendants accessibles sous le nouveau préfixe, sans créer de nouveaux bindings pour chacun d’eux: les relations enfant restent l’état de la collection commune.

Le nombre de chemins peut donc croître plus vite que le nombre de ressources. Si une collection reçoit un binding vers elle-même ou vers un ancêtre, les URI peuvent répéter indéfiniment le même segment.

Le serveur doit détecter les boucles de collections pendant le traitement d’une requête Depth: infinity. Il peut refuser à l’avance la création d’une boucle, car leur prise en charge est facultative. S’il les accepte, il doit abandonner l’hypothèse qu’une profondeur infinie signifie une simple marche dans un arbre.

Le problème n’est pas l’infinité des données stockées. C’est l’infinité que pourrait fabriquer un algorithme en confondant chaque chemin avec une nouvelle ressource.

L’identité devait survivre aux déplacements de chemin

Deux URI différentes ne prouvent pas deux objets. Deux contenus égaux ne prouvent pas non plus un seul objet: deux ressources indépendantes peuvent avoir exactement les mêmes octets puis diverger.

RFC 5842 rend donc obligatoire DAV:resource-id. Sa valeur est attribuée à la création, unique parmi toutes les ressources pour toujours, stable lors d’une mise à jour ou d’un REBIND, et jamais réattribuée même si aucune URI ne donne plus accès à la ressource.

Lorsque deux résultats obtenus par des bindings différents contiennent le même identifiant caractère pour caractère, le client sait qu’ils atteignent le même objet. L’identifiant ne choisit pas une adresse préférée. Il décrit ce qui reste lorsque les adresses changent.

Une requête PROPFIND peut demander cette propriété pour reconstruire exactement la structure des bindings. L’omission d’un sous-arbre devient alors vérifiable plutôt qu’intuitive.

Le parcours avait besoin de deux registres

Un registre de chemins répond à la question: par quelles relations cette ressource apparaît-elle dans l’espace de noms ? Un registre d’identités répond à une autre question: quelles collections ont déjà eu leurs descendants énumérés dans cette réponse ?

Utiliser seulement le premier conserve toutes les arêtes mais répète le travail et suit les cycles. Utiliser seulement le second empêche la récursion, mais risque de supprimer une URI valide avant même de l’avoir enregistrée.

Un client fidèle ajoute donc chaque binding au graphe, puis décide séparément si l’identité cible doit être développée. Ce n’est qu’après avoir conservé l’arête qu’il peut reconnaître un développement déjà fait.

208 est la preuve transmise entre ces deux registres: ce chemin est réel; son sous-arbre n’est pas absent, il a déjà été décrit par une autre occurrence de la même identité.

Already Reported conservait précisément le second chemin

La règle normative est étroite. 208 peut apparaître dans un DAV:propstat pour un PROPFIND Depth: infinity. Parmi plusieurs bindings vers une même collection dans la portée, un seul est rapporté avec 200. Les éléments DAV:response correspondant aux bindings suivants portent 208 et aucun élément pour leurs descendants n’est répété.

L’élément du binding suivant n’est pas supprimé. Son href reste dans le corps et son DAV:resource-id peut le relier à l’occurrence développée avec 200.

Dans l’exemple de la spécification, /Coll/ et /Coll/Bar portent le même identifiant. Le premier chemin reçoit 200 et montre les membres. Le second reçoit 208. Le serveur ne poursuit pas /Coll/Bar/Bar/Bar, car cette succession ne révèle jamais une nouvelle collection.

« Déjà rapporté » qualifie les descendants dans le compte rendu en cours. Il ne dit pas que le chemin lui-même a cessé d’exister.

Le chemin choisi pour 200 ne devenait pas canonique

Le serveur doit choisir une occurrence par laquelle développer la collection. Cette décision rend la réponse finie; elle ne confère aucun droit durable au chemin choisi.

Le premier 200 n’est ni l’URI originale, ni une racine souveraine, ni une autorisation de masquer les autres bindings. Ces derniers demeurent des relations indépendantes appartenant à l’état de leurs collections parentes.

Si un client élève le chemin 200 au rang de vérité unique, il perd l’emplacement, le contexte d’autorisation et l’historique attachés aux chemins 208. Il peut ensuite confondre UNBIND avec la destruction de la ressource, ou attribuer à un parent le contrôle d’arêtes qui appartiennent à d’autres collections.

Le coût du parcours peut être attribué à une occurrence. L’identité et la gouvernance des chemins ne le peuvent pas.

207 restait l’enveloppe du récit

Au niveau de la requête HTTP, la réponse est normalement 207 Multi-Status. Le 208 se trouve dans le corps, à l’intérieur du résultat de propriétés d’une occurrence.

Cette imbrication empêche d’interpréter 208 comme « vous avez déjà envoyé cette requête » ou « tout le traitement a déjà eu lieu ». Elle ne parle que d’un binding vers une collection dont les descendants ont été énumérés ailleurs dans le même compte rendu.

Le href garde l’identité du chemin. Le resource-id relie plusieurs chemins à la même ressource. Les statuts intérieurs indiquent quelle occurrence a fourni les propriétés et laquelle s’appuie sur une énumération antérieure.

Un intermédiaire qui transforme le corps en un simple booléen de succès détruit ce modèle. Il préserve la lettre 207 mais perd le graphe.

Une omission exigeait une capacité partagée

Un sous-arbre absent peut signifier « déjà énuméré » ou « jamais renvoyé ». Sans connaissance de 208, le client ne peut pas faire la différence.

Le serveur annonce donc la classe de conformité bind dans l’en-tête DAV d’une réponse OPTIONS. Le client devrait envoyer DAV: bind et doit alors comprendre 208.

Pour assurer la compatibilité, le serveur ne devrait pas employer 208 dans Multi-Status si le client n’a pas signalé cette capacité. Un ancien client pourrait traiter le statut inconnu comme une erreur ou conclure que l’alias ne contient aucun membre.

La réduction du corps n’est donc pas une compression privée. Elle repose sur un contrat explicite: le destinataire sait quelle information a été omise, où elle a été donnée et quelle identité permet de faire le lien.

508 représentait l’arrêt, pas une autre forme de 208

Lorsqu’un client non conscient des bindings déclenche une boucle avec Depth: infinity, RFC 5842 préfère 508 Loop Detected. Si la boucle est découverte avant le début de la réponse, 508 peut être le statut extérieur. Si le serveur diffuse déjà un Multi-Status, le défaut peut apparaître dans le relevé.

Le résultat de contrôle diffère. Avec 208, un client préparé reçoit un graphe fini: l’alias est conservé, la répétition est supprimée et le reste du parcours continue. Avec 508, le serveur arrête l’opération parce qu’une boucle infinie a été rencontrée; l’opération échoue.

208 n’est donc pas une réussite indulgente et 508 sa version sévère. Le premier transmet une référence comprise. Le second refuse de laisser un destinataire ignorant prendre une omission pour une structure complète.

Une erreur explicite peut être plus interopérable qu’un succès mal compris.

Le graphe augmentait aussi la surface de risque

La possibilité de créer des bindings facilite les boucles accidentelles ou malveillantes. La détection pendant les parcours profonds est obligatoire, mais elle ne résout pas tous les coûts.

La spécification décrit des risques de déni de service et de confidentialité. Un binding interserveur peut diriger de la charge vers une cible qui ne l’attend pas. La propriété facultative DAV:parent-set peut révéler des emplacements privés et forcer le serveur à entretenir une liste influencée depuis d’autres domaines administratifs.

208 limite une amplification: la répétition des descendants dans une réponse. Il ne définit ni budget CPU, ni plafond de mémoire, ni autorisation de créer des bindings. Même un graphe fini peut être énorme; même un alias exact peut révéler une structure sensible.

Le mécanisme demeure mince parce qu’il ne prétend pas résoudre les problèmes qu’il ne peut pas prouver.

Même ressource ne voulait pas dire même observation

Un resource-id identique garantit l’identité de la ressource, pas l’égalité de toutes les propriétés observées par chaque chemin. Les dead properties sont indépendantes du nombre de bindings et du chemin soumis; les live properties suivent leurs propres définitions et certaines peuvent dépendre du contexte de chemin.

Fusionner toute observation par identifiant efface cette nuance. Considérer toute différence comme une nouvelle ressource nie l’identité stable.

Le modèle utile distingue donc les faits sur la ressource, les faits sur le binding et les observations liées au chemin. Aucun de ces niveaux ne doit annexer les autres.

Cette retenue rejoint un principe plus général de l’Internet: partager l’identité minimale nécessaire à l’interopérabilité, puis laisser les décisions dépendantes du contexte près des opérateurs qui possèdent ce contexte.

IANA enregistre un statut volontairement spécialisé

Le registre IANA des codes d’état HTTP associe actuellement 208 Already Reported à RFC 5842. Le même document Experimental définit 508, tandis que 207 renvoie à RFC 4918 sur la voie Standards Track.

Cette inscription ne fait pas de l’extension un Internet Standard et ne prouve aucun taux de déploiement contemporain. Elle ne transforme pas non plus 208 en code général de déduplication pour bases de données, caches ou API.

Son domaine est précis: une occurrence de binding dans un PROPFIND profond, au sein d’un Multi-Status compris par les deux parties.

La portée étroite est une qualité. Elle empêche un mot séduisant—already—d’acquérir une autorité qu’il n’a jamais reçue.

Tous les chemins, une seule expansion

HTTP 208 n’a pas aplati le graphe en arbre. Il a conservé les deux couches nécessaires pour le décrire.

Chaque binding reste visible parce que les chemins sont de vrais éléments de l’espace de noms. La ressource reçoit une identité durable parce qu’elle ne se réduit à aucun chemin. Les descendants ne sont développés qu’une fois parce qu’une seconde liste n’ajouterait aucune structure. L’omission est marquée parce qu’une absence sans raison ressemble à une perte.

Aucun chemin n’est couronné maître de l’objet. Aucun alias ne devient une copie. Aucun cycle n’oblige le serveur à inventer une infinité de ressources.

La seconde porte reste sur le plan; la salle derrière elle n’a pas besoin d’un second inventaire.