Кратко

  • HTTP 206 подтверждает успешную передачу заявленного диапазона выбранного представления, но сам по себе не доказывает, что отдельно полученные диапазоны образуют полный объект.
  • Для возобновлённой передачи и сборки в кэше нужны общий сильный валидатор, точное покрытие интервалов и итоговая проверка всего представления.
  • Content-Length в ответе 206 обычно измеряет тело этого сообщения, а Content-Range указывает положение части и полную длину выбранного представления.
  • Квитанция сборки диапазонов должна сохранять идентичность представления и каждый принятый интервал, а не считать полный счётчик байтов достаточным доказательством.

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

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

Успешный диапазон имеет ограниченный смысл

RFC 9110 определяет 206 Partial Content как успешное выполнение запроса диапазона посредством передачи одной или нескольких частей выбранного представления. Сервер утверждает, что передал заявленные интервалы, но не утверждает, что клиент получил всё представление.

Получатель должен проверить Content-Type и каждый Content-Range, чтобы понять состав ответа и необходимость новых запросов. Для одного диапазона Content-Range задаёт включительные границы и обычно полную длину. Content-Length, напротив, считает октеты в текущем содержимом сообщения 206. Смешение этих величин превращает корректный частичный ответ в ложный признак полноты.

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

Непрерывность относится к представлению, а не к URL

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

Эту границу защищает If-Range. Клиент отправляет запрос диапазона с валидатором. Если он совпадает, сервер может вернуть нужную часть; если нет, сервер игнорирует Range и возвращает всё новое представление. RFC 9110 запрещает слабый тег сущности в If-Range, потому что побайтовое объединение требует сравнения, надёжно различающего версии.

Поэтому ответ 200 после If-Range — не неэффективная ошибка, которую надо превратить обратно в 206. Это свидетельство того, что старую частичную копию уже нельзя безопасно дополнить. Правильное действие — удалить прежнее состояние сборки и принять новое полное представление.

Кэш наследует ту же обязанность

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

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

Проверяйте целостность на правильном уровне

RFC 9530 разделяет две области. Content-Digest вычисляется для содержимого HTTP-сообщения. Repr-Digest охватывает все данные выбранного представления. В ответе 206 первый может проверить переданный сегмент, а второй — объект, восстановленный через несколько запросов или соединений.

Дайджест не заменяет валидатор. Валидатор связывает фрагменты с одной версией, Repr-Digest проверяет итоговые байты, а интервальный журнал исключает пробелы и перекрытия, скрытые общим счётчиком. Поля целостности также не определяют аутентификацию, авторизацию или конфиденциальность. R063 задаёт более узкий вопрос: образуют ли полученные байты одно согласованное представление.

Создайте квитанцию сборки диапазонов

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

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

Закрывайте квитанцию лишь тогда, когда интервалы точно покрывают представление, а восстановленные байты проходят ожидаемый Repr-Digest или независимый хэш. Если сильный валидатор изменился, исчез или стал неоднозначным, отбросьте смешанную сборку и получите полное текущее представление. Это требует трафика, но защищает более ценное утверждение: обработанный объект действительно существовал как одна версия.

Источники