Кратко

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

Одна цифра — не одна история

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

Причина была исторически практичной. RFC 1945, опубликованный в мае 1996 года, описывал распространённое употребление HTTP/1.0. Документ разделял широко и согласованно реализованные свойства и те, которые встречались редко или работали неодинаково. Один ярлык HTTP/1.0 уже покрывал разные наборы реальных функций. Версия не могла честно служить ведомостью каждого механизма внутри программы.

В RFC 1945 она была определена иначе: как указание на формат сообщения и способность отправителя понимать дальнейшее HTTP-общение, а не на функции, фактически полученные в текущем обмене. Старшая цифра должна была меняться при несовместимом изменении формата. Младшая могла расти, если появлялись новые смысловые возможности без замены общего алгоритма разбора. Одно лишь новое значение в расширяемом поле не требовало очередной версии.

RFC 2068 в январе 1997 года сохранил эту конструкцию и связал её с обязательством отправителя. Определённые им запросы и ответы использовали в первой строке HTTP/1.1. Тем самым отправляющее приложение заявляло, что как минимум условно соответствует спецификации. Версией приложения считалась наивысшая версия HTTP, для которой оно могло поддержать такое соответствие.

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

Простой запрос может быть HTTP/1.1, не используя передачу частями, согласование представления или заметные инструкции для кеша. Номер всё равно полезен получателю: он подсказывает, что отправитель способен понять в ответе или следующем запросе. Но наличие номера не доказывает применения постоянного соединения, chunked-кодирования или любой иной отдельной функции.

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

На следующем участке говорит посредник

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

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

В каждом таком случае ответственность начинается заново. Если прокси HTTP/1.0 бездумно копирует HTTP/1.1 клиента, следующему серверу он обещает способность, которой у него самого может не быть. Если же способный прокси заменяет HTTP/1.0 на HTTP/1.1, это не обязательно фальсификация: для следующего соединения отправителем является уже он.

RFC 2145 был выпущен в мае 1997 года после путаницы, споров и проблем совместимости вокруг толкования номеров. Документ сформулировал результат прямо: версия HTTP относится к отдельному участку, а не к связи от конца до конца. Прокси не «пересылает» номер запроса или ответа как неизменный атрибут первоначального автора.

Отдельное поле Via может хранить сведения о протоколах, заявленных на предыдущих участках. Оно и текущий номер отвечают на разные вопросы. При этом Via не становится неоспоримым полным журналом пути. Когда исходный сервер видит HTTP/1.1, непосредственно доказано заявление его ближайшего соседа; версию разговора браузера с первым посредником можно установить только по наблюдению или надёжной записи того участка.

Новое поле должно пережить собственное удаление

Рост младшей версии не разрешал тайно менять смысл уже известных полей. RFC 2145 уточнил: в пределах одной старшей версии прежние конструкции должны сохранять значение. Получатель обычно может проигнорировать незнакомое поле, а общий синтаксический каркас останется пригодным для разбора.

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

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

Граница особенно ясна на примере из RFC 2145. Сервер HTTP/1.1 не мог ответить на запрос HTTP/1.0 сообщением, которое зависит от Transfer-Encoding: chunked, рассчитывая, что старый клиент просто пропустит неизвестный заголовок. После удаления этого поля клиент не узнает, как размечено тело. Остаток не будет полноценным сообщением старой версии.

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

Что доказывает появление уточняющего RFC

RFC 2145 подчёркивал, что не меняет предполагаемого смысла HTTP/1.0 или HTTP/1.1, а окончательно разъясняет неоднозначные места. Сам факт публикации показывает трение между документацией и реализациями. Но он не сообщает числа затронутых продуктов, их названий, тяжести каждого сбоя или доли трафика. Историю разъяснения нельзя превращать в несуществующую статистику внедрения.

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

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

В 1999 году RFC 2616 сохранил разделение и прямо сослался на RFC 2145. RFC 7230 в 2014 году ещё чётче пояснил, что младшая версия объявляет способность понимать будущее общение, даже если текущее сообщение пользуется лишь обратно совместимым подмножеством. Там же отмечено, что переход от RFC 2068 к RFC 2616 не повысил младшую версию. Новая редакция документа, изменение обязанности и новый сигнал в сетевом сообщении — не одно событие.

RFC 9110 в 2022 году отделил общую семантику HTTP от синтаксисов HTTP/1.1, HTTP/2 и HTTP/3. Эти старшие версии сосуществуют; схему младших версий HTTP/1.1 нельзя механически переносить на их форматы и согласование. При пересылке посредник по-прежнему указывает протокол, применённый им на данном участке, а Via сохраняет отдельный вид сведений о предыдущих участках.

От опубликованного правила до работающей возможности

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

Это сравнение не означает, что авторы HTTP предвидели или одобряли институциональные идеи Lu Heng либо его предложения о распределённых реестрах. Оно лишь удерживает отдельно пять видов свидетельств: доступный RFC, заявленный номер, установленное ПО, использованную функцию и завершённый результат.

RFC 2068 не делал из HTTP/1.1 универсальный сертификат. Он назначал ответственного за ограниченное обещание: тот, кто создаёт сообщение для следующего участка, отвечает за номер, а тот, кто вводит новшество, отвечает за сохранение действительного пути для старого получателя.

Источники