Кратко

  • WebDAV bindings позволяют нескольким URI вести к одному ресурсу. Если это коллекция, второй binding открывает тех же участников по другому префиксу и способен образовать цикл.
  • В понимающем bindings PROPFIND с Depth: infinity одно появление коллекции получает 200 и раскрывает потомков. Последующие пути остаются в DAV:response со статусом 208 Already Reported, но их поддерево не повторяется.
  • DAV:resource-id даёт устойчивую идентичность под меняющимися путями. Клиент хранит каждое ребро и разворачивает общий узел один раз; непонимающему клиенту петля возвращает 508, а не неявно сокращённый граф.

Два указателя не создавали второе хранилище

Один архивный зал может иметь две двери из разных коридоров. Обе двери существуют, принадлежат своим участкам здания и меняют его навигацию. Но шкафы за ними не удваиваются.

Обходчик, считающий путь объектом, войдёт дважды и дважды запишет всё содержимое. Если один коридор возвращается к предку, он породит бесконечную последовательность имён в конечном здании. Обходчик, выбрасывающий вторую дверь при распознавании комнаты, остановится ценой неверного плана.

208 выбрал точнее: записать вторую дверь, связать её с уже развёрнутым залом и не повторять внутреннюю опись.

Протокол сохранил граф и удалил лишь повтор вычисления.

WebDAV уже требовал читать внутренние результаты 207

RFC 4918 2007 года определяет состояние коллекции WebDAV как mappings между сегментами пути и ресурсами плюс свойства самой коллекции. Имя участника — отношение доступа, а не ресурс.

PROPFIND использует глубину 0, 1 или infinity. При бесконечной глубине запрос охватывает всех потомков. Сервер возвращает общий 207 Multi-Status с плоским списком DAV:response; href называет путь, а propstat содержит статусы запрошенных свойств.

Внешний 207 не был единым приговором. Клиент обязан читать внутренний отчёт. Позже 208 занял именно этот уровень: он относится к одному появлению binding, но не объявляет весь HTTP-запрос ранее выполненным.

Основной WebDAV признавал несколько URI у ресурса. Расширение добавило метод, которым клиент мог создать новый путь к существующему объекту.

BIND создавал ребро, а не копию

Экспериментальный RFC 5842, опубликованный в апреле 2010 года, определяет BIND, UNBIND и REBIND. BIND связывает сегмент в коллекции с существующим ресурсом. Новый URI становится ещё одним обычным адресом того же объекта.

Новым является binding. Ресурс не копируется. Две родительские коллекции могут хранить два независимых отношения к одной цели.

Binding integrity требует, чтобы связь продолжала существовать и указывать на ту же идентичность, пока определённая операция явно её не уберёт или не изменит. Удаление одной связи не должно ломать другую или освобождать ресурс, пока остаётся иной binding.

Псевдоним — не владелец объекта, но и не декоративный дубликат. Это отдельное состояние родительской коллекции.

Binding коллекции проецировал её потомков

Связь с листовым ресурсом добавляет новый URI. Связь с коллекцией делает её участников доступными под новым префиксом, не создавая новых внутренних bindings для каждого ребёнка.

Поэтому количество URI mappings способно расти без роста числа ресурсов. Связь коллекции с собой или предком создаёт пути, в которых один сегмент повторяется сколько угодно раз.

RFC 5842 требует обнаруживать циклы коллекций при обработке Depth: infinity. Сервер вправе не позволять их создание, поскольку поддержка циклов необязательна. Если цикл принят, обход обязан работать с графом.

Бесконечно не хранилище. Бесконечен результат алгоритма, который всякий новый путь принимает за новый объект.

resource-id переживал смену адресов

Разные URI не доказывают разные ресурсы. Совпадающее содержимое тоже не доказывает один ресурс: независимые объекты могут временно быть одинаковыми.

RFC 5842 требует DAV:resource-id. Значение назначается при создании, уникально среди всех ресурсов навсегда, не меняется при обновлении существующего ресурса или REBIND и не переиспользуется даже после исчезновения всех доступных URI.

Одинаковые посимвольно идентификаторы, прочитанные через разные bindings, подтверждают общий объект. Идентификатор не выбирает главный путь. Он остаётся стабильным под всеми адресами.

Клиент может запросить его в PROPFIND и доказуемо восстановить, какие рёбра ведут к одному узлу и почему отсутствие повторных потомков не является потерей.

Для графа понадобились два журнала

Журнал рёбер хранит родителя, сегмент и href каждого binding. Журнал раскрытий хранит, какие идентичности коллекций уже отдали потомков в текущем ответе.

Только пути сохраняют топологию, но повторяют работу и следуют циклу. Только resource-id прекращают цикл, но могут стереть реальное ребро до его регистрации.

Сначала нужно записать binding, затем решить, следует ли снова раскрывать целевой узел. Дедупликация применяется к рекурсии, не к пространству имён.

208 связывает журналы: этот путь существует, а его коллекция уже раскрыта через другое появление.

Последующий binding оставался в теле

Точная область 208 — DAV:propstat в запросе Depth: infinity. Среди нескольких bindings к одной коллекции одно появление получает 200. Для остальных сохраняются DAV:response со статусом 208, но ответы их потомков не включаются.

Последующий href не исчезает. Его resource-id связывает путь с прежним 200.

В примере RFC /Coll/ и /Coll/Bar имеют один ID. Первый путь получает 200 и показывает участников. Второй получает 208. Обход не строит /Coll/Bar/Bar, потому что снова пришёл к тому же узлу.

Already Reported описывает историю раскрытия внутри данного Multi-Status, а не право удалить URI.

Первое 200 не назначало канонического хозяина

Для конечного ответа сервер выбирает одно появление носителем подграфа. Выбор не делает его исходным, постоянным или господствующим адресом.

Каждый binding остаётся состоянием своей родительской коллекции и может нести отдельный контекст навигации, авторизации и аудита. Выбросить пути 208 — значит потерять эти факты.

Тогда UNBIND легко принять за удаление ресурса, а родитель первого пути — за орган, управляющий рёбрами других родителей.

Порядок обхода не должен превращаться в распределение власти.

207 оставался внешним конвертом

На уровне запроса обычно возвращается 207 Multi-Status. 208 расположен в теле, внутри результата свойств конкретного пути.

Он не означает, что клиент повторил HTTP-запрос или весь ответ был отправлен раньше. Он говорит, что потомки этой коллекции уже перечислены в том же документе через другой binding.

href хранит путь, resource-id соединяет пути с объектом, а 200/208 показывают место раскрытия.

Посредник, превращающий всё в булев успех, сохраняет код конверта и уничтожает доказательства графа.

Сокращение требовало общего понимания

Отсутствующий подграф может быть уже сообщён или потерян. Клиент без знания 208 не отличает одно от другого.

Сервер объявляет класс соответствия bind в заголовке DAV ответа OPTIONS. Клиенту следует послать DAV: bind; после такого сигнала он обязан понимать 208.

Ради обратной совместимости 208 не следует использовать в Multi-Status без сигнала клиента. Старое ПО может принять неизвестный статус за ошибку или счесть коллекцию пустой.

Это не одностороннее сжатие. Обе стороны договариваются, что именно опущено, где оно уже появилось и какая идентичность связывает записи.

508 завершал то, что 208 позволял продолжить

Если не понимающий binding клиент встречает петлю при глубоком PROPFIND, RFC 5842 предписывает 508 Loop Detected. До начала потоковой передачи он может быть верхним статусом; во время уже начатого Multi-Status отказ может появиться внутри отчёта.

С 208 подготовленный клиент продолжает: сохраняет второе ребро и не повторяет подграф. С 508 сервер прекращает операцию из-за бесконечного цикла и фиксирует неуспех.

Это разные управляющие исходы, а не мягкая и строгая формулировка. Один передаёт понятную ссылку, другой ставит предел при отсутствии общего языка.

Явный отказ правдивее внешне успешного, но необъяснимо неполного дерева.

Граф увеличивал поверхность риска

BIND даёт клиентам новый способ создавать случайные и вредоносные петли. Обязательная детекция глубины не исчерпывает угроз.

RFC 5842 отмечает конфиденциальность и denial of service. Межсерверные bindings могут направить нагрузку к неготовой цели. Необязательный DAV:parent-set способен раскрыть приватные расположения и заставить поддерживать списки, на которые влияют другие административные домены.

208 ограничивает повтор в одном ответе. Он не задаёт бюджет CPU, памяти, узлов или размера и не выдаёт права создавать рёбра. Конечный граф тоже может быть огромным.

Тонкий механизм решает одну доказуемую проблему, не притворяясь всей политикой безопасности.

Общий объект не отменял контекст пути

Один resource-id доказывает объектную идентичность, но не одинаковость каждого свойства по каждому пути. Dead properties не зависят от binding и маршрута, а live properties следуют собственным определениям и могут учитывать путь.

Слияние всех наблюдений по ID стирает контекст. Создание нового объекта при любом отличии стирает идентичность.

Нужно отдельно хранить факты ресурса, факты binding и наблюдения маршрута. 208 использует общий ID лишь для решения о повторном раскрытии.

Доказательство не должно получать больше власти, чем позволяет его содержание.

IANA сохранила узкий смысл

Реестр кодов HTTP IANA связывает 208 Already Reported с RFC 5842. Тот же Experimental RFC определяет 508, а 207 ссылается на RFC 4918.

Регистрация не превращает расширение в Internet Standard, не доказывает современное распространение и не делает 208 общим кодом для дублей базы данных, идемпотентности или кэша.

Его место — bind-aware WebDAV, бесконечная глубина и Multi-Status, который клиент умеет читать.

Узость не слабость: она не позволяет слову «already» стать разрешением стирать всё похожее.

Каждое ребро, одно раскрытие

HTTP 208 не маскировал граф под дерево. Он сохранил пути, закрепил объектную идентичность и ограничил вычисление.

Каждый binding сообщается, потому что доступ — реальное состояние. Ресурс получает вечный ID, потому что не принадлежит одному URI. Потомки раскрываются один раз, потому что повтор не добавляет структуры. Пропуск имеет статус, потому что необъяснённое молчание похоже на потерю.

Ни один путь не становится суверенным, псевдоним не становится копией, цикл не превращается в бесконечные ресурсы.

Вторая дверь остаётся на плане. Содержимое общей комнаты не нужно считать снова.