RFC 7230 | Протокол передачи гипертекста (HTTP/1.1): синтаксис сообщения и маршрутизация

Аннотация

Протокол передачи гипертекста (HTTP) — это протокол уровня приложений без сохранения состояния для распределенных, совместных гипертекстовых информационных систем. В этом документе дается обзор архитектуры HTTP и связанной с ней терминологии, определяются схемы универсального идентификатора ресурса (URI) «http» и «https», определяется синтаксис сообщения HTTP/1.1 и требования к синтаксическому анализу, а также описываются связанные проблемы безопасности для реализаций.

Скачать оригинальную версию документа на английском языке RFC 7230 PDF

Оглавление

1. Введение
1.1. Обозначение требований
1.2. Синтаксическая нотация
2. Архитектура
2.1. Обмен сообщениями клиент / сервер
2.2. Разнообразие реализации
2.3. Посредники
2.4. Кэши
2.5. Соответствие и обработка ошибок
2.6. Управление версиями протокола
2.7. Унифицированные идентификаторы ресурса (URI)
2.7.1. Схема http URI
2.7.2. Схема https URI
2.7.3. http и https URI нормализация и сравнение
3. Формат сообщения
3.1. Стартовая линия
3.1.1. Строка запроса
3.1.2. Строка состояния
3.2. Поля заголовка
3.2.1. Расширяемость поля
3.2.2. Порядок полей
3.2.3. Пробелы
3.2.4. Полевой анализ (Синтаксический анализ поля)
3.2.5. Пределы поля
3.2.6. Компоненты значения поля
3.3. Тело сообщения
3.3.1. Transfer-Encoding
3.3.2. Content-Length
3.3.3. Длина тела сообщения
3.4. Обработка неполных сообщений
3.5. Надежность синтаксического анализа сообщения
4. Передача кодирований
4.1. Поблочная передача кодирования
4.1.1. Расширения блока
4.1.2. Поблочная часть трейлера
4.1.3. Поблочное декодирование
4.2. Компрессионное кодирование (Кодировки сжатия)
4.2.1. Сжатое кодирование (Compress Coding)
4.2.2. Опровержение кодирования (Deflate Coding)
4.2.3. Gzip кодирование
4.3. TE поле заголовка
4.4. Трейлер
5. Маршрутизация сообщений
5.1. Определение целевого ресурса
5.2. Подключение входящих
5.3. Запрос цели
5.3.1. Исходная форма (origin-form)
5.3.2. Абсолютная форма (absolute-form)
5.3.3. Авторитетная форма (authority-form)
5.3.4. Звездочная форма (asterisk-form)
5.4. Заголовок «Host» (узел)
5.5. URI действующего запроса
5.6. Связывание ответа на запрос
5.7. Пересылка сообщений
5.7.1. Заголовок «Via»
5.7.2. Трансформации
6. Управление подключением
6.1. Заголовок «Connection»
6.2. Установление
6.3. Упорство
6.3.1. Повторение запросов
6.3.2. Конвейеризация
6.4. Совпадение
6.5. Сбои и таймауты
6.6. Срывание
6.7. Заголовок «Upgrade»
7. Расширение списка ABNF: #rule
8. Соображения IANA
8.1. Регистрация поля заголовка
8.2. Регистрация схемы URI
8.3. Регистрация интернет медиа типа
8.3.1. Интернет медиа тип «message/http»
8.3.2. Интернет медиа тип «application/http»
8.4. Реестр передачи кодирования
8.4.1. Процедура
8.4.2. Постановка на учет (Регистрация)
8.5. Регистрация кодирования контента
8.6. Обновление реестра токенов
8.6.1. Процедура
8.6.2. Обновление регистрации токенов
9. Вопросы безопасности
9.1. Учреждение власти (полномочий)
9.2. Риски посредников
9.3. Атаки через длину элемента протокола
9.4. Разделение ответов
9.5. Запрос контрабанды
9.6. Целостность сообщения
9.7. Конфиденциальность сообщения
9.8. Конфиденциальность информации журнала сервера
10. Благодарности
11. Ссылки
11.1. Нормативные ссылки
11.2. Информационные ссылки
Приложение А. История версий HTTP
A.1. Отличия от HTTP/1.0
A.1.1. Многосетевые веб-серверы
A.1.2. Соединения Keep-Alive
A.1.3. Введение Transfer-Encoding
А.2. Отличия от RFC 2616
Приложение B. Собранный ABNF
Индекс
Адреса авторов

1. Введение

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

  1. «Синтаксис и маршрутизация сообщений» (этот документ)
  2. «Семантика и контент» [RFC7231 #]
  3. «Условные запросы» [RFC7232 #]
  4. «Запросы диапазона» [RFC7233 #]
  5. «Кэширование» [RFC7234 #]
  6. «Аутентификация» [RFC7235 #]

Эта спецификация HTTP/1.1 устарела RFC 2616 # и RFC 2145 # (при HTTP-управлении версиями). Эта спецификация также обновляет использование CONNECT для установления туннеля, ранее определенного в RFC 2817 #, и определяет схему URI «https», которая была неофициально описана в RFC 2818 #.

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

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

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

Этот документ описывает архитектурные элементы, которые используются или упоминаются в HTTP, определяет схемы URI «http» и «https», описывает общую работу сети и управление соединением, а также определяет требования к кадрам и пересылке сообщений HTTP. Наша цель — определить все механизмы, необходимые для обработки сообщений HTTP, которые не зависят от семантики сообщений, и, таким образом, определить полный набор требований для анализаторов сообщений и посредников для пересылки сообщений.

1.1. Обозначение требований

Ключевые слова «ОБЯЗАН — MUST», «НЕ ОБЯЗАН — MUST NOT», «ТРЕБУЕТСЯ — REQUIRED», «ДОЛЖЕН — SHALL», «НЕ ДОЛЖЕН — SHALL NOT», «СЛЕДУЕТ — SHOULD», «НЕ СЛЕДУЕТ — SHOULD NOT», «РЕКОМЕНДУЕТСЯ — RECOMMENDED», «НЕ РЕКОМЕНДУЕТСЯ — NOT RECOMMENDED», «ВОЗМОЖЕН — MAY» и «ДОПОЛНИТЕЛЬНО — OPTIONAL» в этом документе интерпретироваться как описано в [RFC2119 #] [RFC8174 #].

Критерии соответствия и соображения, касающиеся обработки ошибок, определены в разделе 2.5.

1.2. Синтаксическая нотация

В этой спецификации используется нотация расширенной формы Бэкуса-Наура (ABNF) [RFC5234 #] с расширением списка, определенным в разделе 7, которое позволяет компактно определять списки, разделенные запятыми, с помощью оператора «#» (аналогично тому, как «*» оператор указывает на повторение). В приложении B показана собранная грамматика, в которой все операторы списка расширены до стандартной записи ABNF.

Следующие основные правила включены в качестве ссылки, как определено в [RFC5234 #], Приложение B.1: ALPHA (буквы — letters), CR (возврат каретки — carriage return), CRLF (CR LF ), CTL (элементы управления — controls), DIGIT (десятичное 0-9) , DQUOTE (двойная кавычка — double quote), HEXDIG (шестнадцатеричный 0-9 / A-F / a-f), HTAB (горизонтальная табуляция — horizontal tab), LF (перевод строки — line feed), OCTET (любая 8-битная последовательность данных), SP (пробел — space) и VCHAR ( любой видимый [USASCII] символ).

Как правило, имена правил ABNF с префиксом «obs-» обозначают «устаревшие» (obsolete) правила грамматики, которые появляются по историческим причинам.

2. Архитектура

HTTP был создан для архитектуры Всемирной паутины (WWW) и со временем развивался для удовлетворения потребностей в масштабируемости всемирной гипертекстовой системы. Большая часть этой архитектуры отражена в терминологии и синтаксической продукции, используемой для определения HTTP.

2.1. Обмен сообщениями «клиент / сервер»

HTTP — это протокол «запросов/ответов» без сохранения состояния, который работает путем обмена сообщениями (раздел 3) через надежное «connection» (соединение) транспортного или сеансового уровня (раздел 6). HTTP-клиент — это программа, которая устанавливает соединение с сервером с целью отправки одного или нескольких HTTP-запросов. HTTP-сервер — это программа, которая принимает соединения для обслуживания HTTP-запросов путем отправки HTTP-ответов.

Термины «клиент» (client) и «сервер» (server) относятся только к ролям, которые эти программы выполняют для определенного соединения. Одна и та же программа может выступать в качестве клиента для одних подключений и сервера для других. Термин «пользовательский агент» (user agent) относится к любой из различных клиентских программ, которые инициируют запрос, включая (но не ограничиваясь ими) браузеры, пауки (веб-роботы), инструменты командной строки, пользовательские приложения и мобильные приложения. Термин «сервер происхождения» (origin server) относится к программе, которая может инициировать авторитетные ответы для данного целевого ресурса. Термины «отправитель» (sender) и «получатель» (recipient) относятся к любой реализации, которая отправляет или получает данное сообщение соответственно.

HTTP основывается на стандарте унифицированного идентификатора ресурса (URI) [RFC3986 #] для указания целевого ресурса (раздел 5.1) и взаимосвязей между ресурсами. Сообщения передаются в формате, аналогичном тому, который используется Интернет-почтой [RFC5322 #] и Многоцелевыми расширениями Интернет-почты (MIME) [RFC2045 #] (различия между сообщениями HTTP и MIME см. В приложении A из [RFC7231 #]).

Большая часть HTTP-связи состоит из запроса поиска (GET) для представления некоторого ресурса, идентифицируемого URI. В простейшем случае это может быть выполнено с помощью одного двунаправленного соединения (===) между пользовательским агентом (UA) и исходным сервером (O).

       request >
UA ======================================= O
                          < response

Клиент отправляет HTTP-запрос на сервер в форме сообщения с запросом, начиная с строки запроса, содержащей метод, URI и версию протокола (раздел 3.1.1), за которыми следуют поля заголовка, содержащие модификаторы запроса, информацию о клиенте и метаданные представления (раздел 3.2), пустая строка для указания конца раздела заголовка и, наконец, тело сообщения, содержащее тело полезной нагрузки (если есть, раздел 3.3).

Сервер отвечает на запрос клиента, отправляя одно или несколько ответных сообщений HTTP, каждое из которых начинается со строки состояния, которая включает версию протокола, код успеха или ошибки и текстовую фразу причины (раздел 3.1.2), за которой, возможно, следуют поля заголовка содержащий информацию о сервере, метаданные ресурса и метаданные представления (раздел 3.2), пустую строку, указывающую конец раздела заголовка, и, наконец, тело сообщения, содержащее тело полезной нагрузки (если есть, раздел 3.3).

Соединение может использоваться для нескольких обменов запросами / ответами, как определено в разделе 6.3.

В следующем примере показан типичный обмен сообщениями для запроса GET (раздел 4.3.1 [RFC7231 #]) по URI «http://www.example.com/hello.txt«:

Запрос клиента:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

Ответ сервера:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

Hello World! My payload includes a trailing CRLF.

2.2. Разнообразие реализации

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

Термин «пользовательский агент» (user agent) не подразумевает, что существует пользователь, непосредственно взаимодействующий с программным агентом во время запроса. Во многих случаях пользовательский агент устанавливается или настраивается для работы в фоновом режиме и сохраняет свои результаты для последующей проверки (или сохраняет только подмножество тех результатов, которые могут быть интересными или ошибочными). Например, паукам обычно присваивается начальный URI, и он настроен на выполнение определенного поведения при сканировании Интернета в виде гипертекстового графа.

Разнообразие реализации HTTP означает, что не все пользовательские агенты могут предлагать своим пользователям интерактивные предложения или предоставлять адекватные предупреждения по вопросам безопасности или конфиденциальности. В тех немногих случаях, когда эта спецификация требует сообщения пользователю об ошибках, допустимо, чтобы такая отчетность наблюдалась только в консоли ошибок или файле журнала. Аналогичным образом, требования о том, что автоматическое действие должно быть подтверждено пользователем перед продолжением, могут быть выполнены с помощью дополнительных параметров конфигурации, параметров времени выполнения или простого избежания небезопасного действия; подтверждение не подразумевает какого-либо конкретного пользовательского интерфейса или прерывания нормальной обработки, если пользователь уже сделал этот выбор.

2.3. Посредники

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

       >              >             >             >
UA =========== A =========== B =========== C =========== O
           <              <            <             <

На рисунке выше показаны три посредника (A, B и C) между пользовательским агентом и сервером происхождения. Сообщение запроса или ответа, которое проходит всю цепочку, будет проходить через четыре отдельных соединения. Некоторые параметры связи HTTP могут применяться только к соединению с ближайшим соседом, не являющимся туннелем, только к конечным точкам цепочки или ко всем соединениям по цепочке. Хотя диаграмма линейная, каждый участник может участвовать в нескольких одновременных сеансах связи. Например, B может получать запросы от множества клиентов, отличных от A, и / или пересылать запросы на серверы, отличные от C, одновременно с обработкой запроса A. Аналогичным образом, более поздние запросы могут отправляться по другому пути соединений, часто на основе динамической конфигурации для балансировки нагрузки.

Термины «восходящий» (upstream) и «нисходящий» (downstream) используются для описания направленных требований относительно потока сообщений: все сообщения передаются от восходящего к нисходящему. Термины «входящий» (inbound) и «исходящий» (outbound) используются для описания требований к направлению в отношении маршрута запроса: «входящий» означает к исходному серверу и «исходящий» означает к пользовательскому агенту.

«Прокси-сервер» (proxy) — это агент пересылки сообщений, который выбирается клиентом, обычно с помощью локальных правил конфигурации, для получения запросов на некоторый тип (ы) абсолютного URI и попытки удовлетворить эти запросы посредством преобразования через интерфейс HTTP. Некоторые переводы минимальны, например, для прокси-запросов для «http» URI, тогда как для других запросов может потребоваться перевод в и из совершенно других протоколов уровня приложений. Прокси-серверы часто используются для группировки HTTP-запросов организации через общего посредника в целях безопасности, служб аннотаций или общего кэширования. Некоторые прокси предназначены для применения преобразований к выбранным сообщениям или полезным нагрузкам во время их пересылки, как описано в Разделе 5.7.2.

«Шлюз» (gateway) (a.k.a. «обратный прокси-сервер» (reverse proxy)) — это посредник, который действует как исходный сервер для исходящего соединения, но транслирует полученные запросы и перенаправляет их на другой сервер или серверы. Шлюзы часто используются для инкапсуляции устаревших или ненадежных информационных служб, для повышения производительности сервера с помощью «ускоренного» (accelerator) кэширования и для обеспечения разделения или балансировки нагрузки служб HTTP на нескольких компьютерах.

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

«Туннель» (tunnel) действует как слепое реле между двумя соединениями без изменения сообщений. После активации туннель не считается участником HTTP-связи, хотя туннель мог быть инициирован HTTP-запросом. Туннель перестает существовать, когда оба конца ретранслируемого соединения закрыты. Туннели используются для расширения виртуального соединения через посредника, например, когда безопасность транспортного уровня (TLS, [RFC5246 #]) используется для установления конфиденциальной связи через общий прокси-сервер брандмауэра.

Указанные выше категории для посредников учитывают только тех, кто выступает в качестве участников HTTP-связи. Существуют также посредники, которые могут действовать на нижних уровнях стека сетевых протоколов, фильтруя или перенаправляя HTTP-трафик без ведома или разрешения отправителей сообщений. Сетевые посредники неотличимы (на уровне протокола) от атаки «человек посередине», часто приводя к недостаткам безопасности или проблемам взаимодействия из-за ошибочного нарушения семантики HTTP.

Например, «прокси-сервер перехвата» (interception proxy) [RFC3040 #] (также широко известный как «прозрачный прокси-сервер» (transparent proxy) [RFC1919 #] или «портал авторизации» (captive portal)) отличается от прокси-сервера HTTP, поскольку он не выбран клиентом. Вместо этого прокси-сервер перехвата фильтрует или перенаправляет исходящие пакеты TCP-порта 80 (и иногда другой общий трафик порта). Прокси-серверы перехвата обычно находятся в общедоступных точках доступа к сети, как средство обеспечения подписки на учетную запись до разрешения использования нелокальных служб Интернета, а также в корпоративных брандмауэрах для обеспечения соблюдения политик использования сети.

HTTP определяется как протокол без сохранения состояния, что означает, что каждое сообщение с запросом можно понимать изолированно. Многие реализации зависят от конструкции HTTP без сохранения состояния для повторного использования прокси-соединений или динамических запросов балансировки нагрузки между несколькими серверами. Следовательно, сервер НЕ ДОЛЖЕН предполагать, что два запроса к одному и тому же соединению поступают от одного и того же пользовательского агента, если соединение не защищено и не привязано к этому агенту. Известно, что некоторые нестандартные расширения HTTP (например, [RFC4559 #]) нарушают это требование, что приводит к проблемам безопасности и совместимости.

2.4. Кэши

«Кэш» (cache) — это локальное хранилище предыдущих ответных сообщений и подсистема, которая управляет хранением, поиском и удалением сообщений. Кэш хранит кешируемые ответы, чтобы уменьшить время ответа и потребление пропускной способности сети при будущих эквивалентных запросах. Любой клиент или сервер МОЖЕТ использовать кеш, хотя кеш не может использоваться сервером, пока он действует как туннель.

Эффект кэша заключается в том, что цепочка запросов / ответов укорачивается, если один из участников цепочки имеет кэшированный ответ, применимый к этому запросу. Следующее иллюстрирует результирующую цепочку, если B имеет кэшированную копию более раннего ответа от O (через C) на запрос, который не был кэширован UA или A.

      >              >
UA =========== A =========== B - - - - - - C - - - - - - O
          <              <

Ответ является «кэшируемым» (cacheable), если в кеше разрешено хранить копию ответного сообщения для использования при ответе на последующие запросы. Даже когда ответ кэшируется, клиент или исходный сервер могут накладывать дополнительные ограничения на то, когда этот кэшированный ответ можно использовать для конкретного запроса. Требования HTTP для поведения кеша и кешируемых ответов определены в разделе 2 [RFC7234 #].

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

2.5. Соответствие и обработка ошибок

Эта спецификация нацелена на критерии соответствия в соответствии с ролью участника в HTTP-коммуникации. Следовательно, HTTP-требования предъявляются к отправителям, получателям, клиентам, серверам, пользовательским агентам, посредникам, исходным серверам, прокси-серверам, шлюзам или кэшам, в зависимости от того, какое поведение ограничено требованием. Дополнительные (социальные) требования предъявляются к реализациям, владельцам ресурсов и регистрации элементов протокола, когда они применяются за пределами одного сообщения.

Глагол «генерировать» (generate) используется вместо «отправить» (send), когда требование различает создание элемента протокола и простую пересылку полученного элемента в нисходящем направлении.

Реализация считается соответствующей, если она соответствует всем требованиям, связанным с ролями, которые она выполняет в HTTP.

Соответствие включает в себя как синтаксис, так и семантику элементов протокола. Отправитель НЕ ДОЛЖЕН генерировать элементы протокола, которые передают значение, известное этому отправителю как ложное. Отправитель НЕ ДОЛЖЕН генерировать элементы протокола, которые не соответствуют грамматике, определенной соответствующими правилами ABNF. В данном сообщении отправитель НЕ ДОЛЖЕН генерировать элементы протокола или синтаксические альтернативы, которые могут быть сгенерированы только участниками других ролей (то есть роли, которую отправитель не имеет для этого сообщения).

Когда полученный элемент протокола анализируется, получатель ДОЛЖЕН иметь возможность анализировать любое значение разумной длины, которое применимо к роли получателя и которое соответствует грамматике, определенной соответствующими правилами ABNF. Обратите внимание, что некоторые полученные элементы протокола могут быть не проанализированы. Например, посредник, пересылающий сообщение, может проанализировать поле заголовка на общие компоненты «field-name» и «field-value», но затем переслать поле заголовка без дальнейшего анализа внутри значения поля.

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

Как минимум, получатель ДОЛЖЕН иметь возможность анализировать и обрабатывать длины элементов протокола, которые по меньшей мере равны значениям, которые он генерирует для тех же элементов протокола в других сообщениях. Например, исходный сервер, который публикует очень длинные ссылки URI на свои собственные ресурсы, должен иметь возможность анализировать и обрабатывать эти же ссылки при получении в качестве цели запроса.

Получатель ДОЛЖЕН интерпретировать полученный элемент протокола в соответствии с семантикой, определенной для него настоящей спецификацией, включая расширения этой спецификации, если только получатель не определил (из опыта или конфигурации), что отправитель неправильно реализует то, что подразумевается в этой семантике. Например, исходный сервер может игнорировать содержимое полученного поля заголовка Accept-Encoding, если проверка поля заголовка User-Agent указывает на конкретную версию реализации, которая, как известно, дает сбой при получении определенных кодировок содержимого.

Если не указано иное, получатель МОЖЕТ попытаться восстановить используемый элемент протокола из недопустимой конструкции. HTTP не определяет конкретные механизмы обработки ошибок, за исключением случаев, когда они оказывают непосредственное влияние на безопасность, поскольку различные приложения протокола требуют разных стратегий обработки ошибок. Например, веб-браузер может пожелать прозрачного восстановления после ответа, когда поле заголовка Location не анализируется в соответствии с ABNF, в то время как клиент управления системой может рассматривать любую форму восстановления после ошибок как опасную.

2.6. Управление версиями протокола

HTTP использует схему нумерации «<major>.<minor>» для указания версий протокола. Эта спецификация определяет версию «1.1«. Версия протокола в целом указывает на соответствие отправителя требованиям, изложенным в соответствующей спецификации HTTP этой версии.

Версия HTTP-сообщения указывается в поле HTTP-версии в первой строке сообщения. HTTP-версия чувствительна к регистру.

HTTP-version = HTTP-name "/" DIGIT "." DIGIT
HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive

Номер версии HTTP состоит из двух десятичных цифр, разделенных знаком «.» (точка или десятичная точка). Первая цифра («основная версия — major version») указывает синтаксис обмена сообщениями HTTP, тогда как вторая цифра («младшая версия — minor version») указывает наивысшую младшую версию в той основной версии, которой отправитель соответствует и может понять для дальнейшего обмена данными. Дополнительная версия объявляет о возможностях связи отправителя, даже если отправитель использует только обратно-совместимое подмножество протокола, что позволяет получателю знать, что более расширенные функции могут использоваться в ответе (серверами) или в будущих запросах (клиентами).

Когда сообщение HTTP/1.1 отправляется получателю HTTP/1.0 [RFC1945 #] или получателю, чья версия неизвестна, сообщение HTTP/1.1 создается таким образом, что его можно интерпретировать как действительное сообщение HTTP/1.0, если все новые функции игнорируются. Эта спецификация накладывает требования к версии получателя на некоторые новые функции, так что совместимый отправитель будет использовать совместимые функции только до тех пор, пока он не определит, посредством конфигурации или получения сообщения, что получатель поддерживает HTTP/1.1.

Интерпретация поля заголовка не изменяется между второстепенными версиями одной и той же основной версии HTTP, хотя поведение получателя по умолчанию при отсутствии такого поля может измениться. Если не указано иное, поля заголовка, определенные в HTTP/1.1, определены для всех версий HTTP/1.x. В частности, поля заголовка Host и Connection должны быть реализованы всеми реализациями HTTP/1.x независимо от того, объявляют ли они о соответствии HTTP/1.1.

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

Посредники, которые обрабатывают сообщения HTTP (т. е. Все посредники, кроме тех, которые действуют как туннели), ДОЛЖНЫ отправлять свою собственную версию HTTP в переадресованных сообщениях. Другими словами, им не разрешается слепо пересылать первую строку HTTP-сообщения, не гарантируя, что версия протокола в этом сообщении соответствует версии, которой этот посредник совместим как для приема, так и для отправки сообщений. Пересылка HTTP-сообщения без переписывания HTTP-версии может привести к ошибкам связи, когда нижестоящие получатели используют версию отправителя сообщения, чтобы определить, какие функции безопасно использовать для последующего взаимодействия с этим отправителем.

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

Клиент МОЖЕТ отправить более низкую версию запроса, если известно, что сервер неправильно реализует HTTP-спецификацию, но только после того, как клиент предпринял хотя бы один нормальный запрос и определил по полям кода статуса ответа или полей заголовка (например, Server), что Сервер неправильно обрабатывает версии более высоких запросов.

Сервер ДОЛЖЕН отправить версию ответа, равную наивысшей версии, которой соответствует сервер, основная версия которой меньше или равна версии, полученной в запросе. Сервер НЕ ДОЛЖЕН отправлять версию, которой он не соответствует. Сервер может отправить ответ 505 (версия HTTP не поддерживается), если он по какой-либо причине желает отказаться от обслуживания основной версии протокола клиента.

Сервер МОЖЕТ отправить ответ HTTP/1.0 на запрос, если известно или подозревается, что клиент неправильно реализует спецификацию HTTP и не способен правильно обрабатывать ответы более поздних версий, например, когда клиенту не удается правильно проанализировать номер версии или когда известно, что посредник слепо перенаправляет HTTP-версию, даже если она не соответствует данной второстепенной версии протокола. Такие понижения протокола НЕ ДОЛЖНЫ выполняться, если они не инициированы конкретными атрибутами клиента, например, когда одно или несколько полей заголовка запроса (например, User-Agent) однозначно соответствуют значениям, отправленным клиентом, о котором известно, что он содержит ошибку.

Смысл версионного дизайна HTTP заключается в том, что старшее число будет увеличиваться только в том случае, если введен несовместимый синтаксис сообщения, и что младшее число будет увеличиваться только в том случае, если изменения, внесенные в протокол, приводят к добавлению в семантику сообщения или подразумевают дополнительную Возможности отправителя. Однако младшая версия не была увеличена для изменений, внесенных между [RFC2068 #] и [RFC2616 #], и эта редакция специально избежала любых таких изменений в протоколе.

Когда получено сообщение HTTP с основным номером версии, который реализует получатель, но с меньшим младшим номером версии, чем тот, который реализует получатель, получатель ДОЛЖЕН обработать сообщение, как если бы оно было в самой младшей младшей версии в той основной версии, для которой получатель соответствует. Получатель может предположить, что сообщение с более младшей версией, отправленное получателю, который еще не указал поддержку этой более высокой версии, является достаточно обратно-совместимым, чтобы безопасно обрабатываться любой реализацией той же основной версии.

2.7. Унифицированные идентификаторы ресурса (URI)

Унифицированные идентификаторы ресурсов (URI) [RFC3986 #] используются по всему HTTP как средство для идентификации ресурсов (раздел 2 [RFC7231 #]). Ссылки URI используются для нацеливания запросов, указания перенаправлений и определения отношений.

Определения «URI-reference» (URI-ссылка), «absolute-URI» (абсолютный URI), «relative-part» (относительная часть), «scheme» (схема), «authority» (полномочия/основания), «port» (порт), «host» (хост), «path-abempty» (свободный путь), «segment» (сегмент), «query» (запрос) и «fragment» (фрагмент) взят из общего синтаксиса URI. Правило «absolute-path» (абсолютного пути) определено для элементов протокола, которые могут содержать непустой компонент пути. (Это правило немного отличается от правила отсутствия пути в RFC 3986, которое допускает использование пустого пути в ссылках, и правила абсолютного пути, который не допускает пути, начинающиеся с двух косых вертикальных линий «//».)  Правило «partial-URI» (частичный URI) определено для элементов протокола, которые могут содержать относительный URI, но не компонент фрагмента.

URI-reference = <URI-reference, смотри [RFC3986 #], Раздел 4.1>
absolute-URI = <absolute-URI, смотри [RFC3986 #], Раздел 4.3>
relative-part = <relative-part, смотри [RFC3986 #], Раздел 4.2>
scheme = <scheme, смотри [RFC3986 #], Раздел 3.1>
authority = <authority, смотри [RFC3986 #], Раздел 3.2>
uri-host = <host, смотри [RFC3986 #], Раздел 3.2.2>
port = <port, смотри [RFC3986], Раздел 3.2.3>
path-abempty = <path-abempty, смотри [RFC3986 #], Раздел 3.3>
segment = <segment, смотри [RFC3986 #], Раздел 3.3>
query = <query, смотри [RFC3986 #], Раздел 3.4>
fragment = <fragment, смотри [RFC3986 #], Раздел 3.5>

absolute-path = 1*( "/" segment )
partial-URI = relative-part [ "?" query ]

Термин из URI Определено в  RFC 3986
URI-reference Раздел 4.1
absolute-URI Раздел 4.3
relative-part Раздел 4.2
scheme Раздел 3.1
authority Раздел 3.2
uri-host Раздел 3.2.2
port Раздел 3.2.3
path-abempty Раздел 3.3
segment Раздел 3.3
query Раздел 3.4
fragment Раздел 3.5

Таблица

Каждый элемент протокола в HTTP, который допускает ссылку на URI, будет указывать в своей продукции ABNF, допускает ли элемент какую-либо форму ссылки (URI-reference), только URI в абсолютной форме (absolute-URI), только путь и дополнительные компоненты запроса, или некоторая комбинация вышеперечисленного. Если не указано иное, ссылки на URI анализируются относительно действующего URI запроса (раздел 5.5).

2.7.1. Схема http URI

Схема URI «http» тем самым определяется с целью минимизации идентификаторов в соответствии с их связью с иерархическим пространством имен, управляемым потенциальным исходным сервером HTTP, прослушивающим соединения TCP ([RFC0793 #]) на данном порту.

http-URI = "http:" "//" authority path-abempty [ "?" query ] [ "#" fragment ]

Исходный сервер для «http» URI идентифицируется компонентом authority (полномочие), который включает идентификатор хоста и необязательный порт TCP ([RFC3986 #], раздел 3.2.2). Компонент иерархического пути и необязательный компонент запроса служат в качестве идентификатора потенциального целевого ресурса в пространстве имен этого исходного сервера. Необязательный компонент фрагмента позволяет косвенно идентифицировать вторичный ресурс, независимо от схемы URI, как определено в разделе 3.5 [RFC3986 #].

Отправитель НЕ ДОЛЖЕН генерировать URI «http» с пустым идентификатором хоста. Получатель, который обрабатывает такую ссылку URI, ДОЛЖЕН отклонить ее как недействительную.

Если идентификатор хоста предоставлен в виде IP-адреса, исходный сервер является прослушивателем (если есть) на указанном TCP-порте с этим IP-адресом. Если host является зарегистрированным именем, зарегистрированное имя является косвенным идентификатором для использования со службой разрешения имен, такой как DNS, для поиска адреса для этого исходного сервера. Если подкомпонент порта пуст или не указан, по умолчанию используется TCP-порт 80 (зарезервированный порт для служб WWW).

Обратите внимание, что наличие URI с данным компонентом authority (полномочие) не означает, что всегда есть HTTP-сервер, прослушивающий соединения на этом хосте и порте. Любой может чеканить URI. Компонент authority определяет, кто имеет право авторитетно отвечать на запросы, направленные на указанный ресурс. Делегированная природа зарегистрированных имен и IP-адресов создает федеративное пространство имен, основанное на управлении указанным хостом и портом, независимо от того, присутствует ли сервер HTTP. См. Раздел 9.1 для соображений безопасности, связанных с установлением authority.

Когда URI «http» используется в контексте, который требует доступа к указанному ресурсу, клиент МОЖЕТ попытаться получить доступ, разрешив хосту IP-адрес, установив TCP-соединение с этим адресом на указанном порту и отправив HTTP сообщение запроса (раздел 3), содержащее идентифицирующие данные URI (раздел 5) на сервер. Если сервер отвечает на этот запрос с помощью временного сообщения ответа HTTP, как описано в Разделе 6 [RFC7231 #], то этот ответ считается официальным ответом на запрос клиента.

Хотя HTTP не зависит от транспортного протокола, схема «http» специфична для служб на основе TCP, поскольку процесс делегирования имени зависит от TCP для установления authority (полномочий). Служба HTTP, основанная на каком-либо другом базовом протоколе соединения, предположительно будет идентифицирована с использованием другой схемы URI, так же как схема «https» (ниже) используется для ресурсов, которые требуют сквозного защищенного соединения. Другие протоколы также могут использоваться для предоставления доступа к идентифицированным ресурсам http — это только официальный интерфейс, который является специфическим для TCP.

Общий синтаксис URI для authority (полномочий) также включает в себя устаревший подкомпонент «userinfo» ([RFC3986 #], раздел 3.2.1) для включения информации аутентификации пользователя в URI. Некоторые реализации используют компонент «userinfo» для внутренней конфигурации информации аутентификации, например, в параметрах вызова команд, файлах конфигурации или списках закладок, даже если такое использование может раскрыть идентификатор пользователя или пароль. Отправитель НЕ ДОЛЖЕН генерировать подкомпонент «userinfo» (и его разделитель «@»), когда в сообщении генерируется ссылка URI «http» в качестве цели запроса или значения поля заголовка. Перед использованием ссылки на URI «http», полученной из ненадежного источника, получателю СЛЕДУЕТ проанализировать «userinfo» и обработать его наличие как ошибку; скорее всего, он используется, чтобы скрыть авторитет ради фишинговых атак.

2.7.2. Схема https URI

Схема URI «https» тем самым определяется с целью минимизации идентификаторов в соответствии с их связью с иерархическим пространством имен, управляемым потенциальным исходным сервером HTTP, прослушивающим данный порт TCP для соединений, защищенных TLS ([RFC5246 #]).

Все перечисленные выше требования для схемы «http» также являются требованиями для схемы «https», за исключением того, что TCP-порт 443 является значением по умолчанию, если подкомпонент порта пуст или не задан, а пользовательский агент ДОЛЖЕН гарантировать, что его соединение с исходный сервер защищен с помощью сквозного шифрования перед отправкой первого HTTP-запроса.

https-URI = "https:" "//" authority path-abempty [ "?" query ] [ "#" fragment ]

Обратите внимание, что схема URI «https» зависит от TLS и TCP для установления authority (полномочий). Ресурсы, доступные через схему «https», не имеют общего идентификатора со схемой «http», даже если их идентификаторы ресурсов указывают одинаковые authority (полномочия) (один и тот же хост, прослушивающий один и тот же порт TCP). Они представляют собой отдельные пространства имен и считаются различными серверами происхождения. Однако расширение HTTP, которое определено для применения ко всем доменам хоста, такое как протокол Cookie [RFC6265 #], может позволить информации, установленной одной службой, влиять на связь с другими службами в соответствующей группе доменов хоста.

Процесс авторизованного доступа к идентифицированному ресурсу https определен в [RFC2818 #].

2.7.3. http и https URI нормализация и сравнение

Поскольку схемы «http» и «https» соответствуют универсальному синтаксису URI, такие URI-нормализация и URI-сравнивание в соответствии с алгоритмом, определенным в разделе 6 [RFC3986 #], с использованием значений по умолчанию, описанных выше для каждой схемы.

Если порт равен порту по умолчанию для схемы, обычной формой является пропуск подкомпонента порта. Когда не используется в абсолютной форме в качестве цели запроса OPTIONS, пустой компонент пути эквивалентен абсолютному пути «/», поэтому в обычной форме вместо этого необходимо указать путь «/». Схема и хост не чувствительны к регистру и обычно представлены в нижнем регистре; все остальные компоненты сравниваются с учетом регистра. Символы, отличные от указанных в «зарезервированном» наборе, эквивалентны их октетам, закодированным в процентах: обычная форма — не кодировать их (см. раздел 2.1 и раздел 2.2 [RFC3986 #]).

Например, следующие три URI эквивалентны:

http://example.com:80/~smith/home.html
http://EXAMPLE.com/%7Esmith/home.html
http://EXAMPLE.com:/%7esmith/home.html

3. Формат сообщения

Все сообщения HTTP/1.1 состоят из начальной строки, за которой следует последовательность октетов в формате, аналогичном формату Интернет-сообщения [RFC5322 #]: ноль или более полей заголовка (вместе именуемых «headers» (заголовки) или «header section» (раздел заголовка) ), пустая строка, указывающая конец раздела заголовка, и необязательное тело сообщения.

HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body ]

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

Получатель ДОЛЖЕН проанализировать сообщение HTTP как последовательность октетов в кодировке, которая является надмножеством US-ASCII [USASCII]. Анализ HTTP-сообщения как потока символов Unicode без учета конкретной кодировки создает уязвимости безопасности из-за различных способов обработки библиотеками обработки строк недопустимых много-байтовых последовательностей символов, которые содержат октет LF (% x0A). Анализаторы на основе строк могут безопасно использоваться только в элементах протокола после того, как элемент извлечен из сообщения, например, в значении поля заголовка после того, как синтаксический анализ сообщения очертил отдельные поля.

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

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

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

3.1. Стартовая линия (Start Line)

HTTP-сообщение может быть либо запросом от клиента к серверу, либо ответом от сервера к клиенту. Синтаксически два типа сообщений отличаются только начальной строкой, которая является либо строкой запроса (для запросов), либо строкой состояния (для ответов), и алгоритмом определения длины тела сообщения (раздел 3.3).

Теоретически, клиент мог получать запросы, а сервер мог получать ответы, различая их по разным форматам начальной строки, но на практике серверы реализованы так, чтобы ожидать только запрос (ответ интерпретируется как неизвестный или недопустимый метод запроса. ) и клиенты реализованы так, чтобы ожидать только ответа.

start-line = request-line / status-line

3.1.1. Строка запроса (Request Line)

Строка запроса начинается с токена метода, за которым следует один пробел (SP), цель-запрос, еще один пробел (SP), версия протокола и заканчивается CRLF.

request-line = method SP request-target SP HTTP-version CRLF

Маркер метода указывает метод запроса, который должен быть выполнен на целевом ресурсе. Метод запроса чувствителен к регистру.

method = token

Методы запроса, определенные в этой спецификации, можно найти в Разделе 4 [RFC7231 #] вместе с информацией, касающейся реестра методов HTTP и соображениями по определению новых методов.

request-target (Запрос-цель) идентифицирует целевой ресурс, к которому следует применить запрос, как определено в разделе 5.3.

Получатели обычно разбивают строку запроса на составляющие ее части, разбивая пробел (см. Раздел 3.5), поскольку пробел в трех компонентах не допускается. К сожалению, некоторые пользовательские агенты не могут правильно кодировать или исключать пробелы, найденные в ссылках гипертекста, в результате чего эти запрещенные символы отправляются в request-target.

Получатели недопустимой строки запроса ДОЛЖНЫ отвечать либо ошибкой 400 (неверный запрос), либо перенаправлением 301 (перемещено навсегда) с правильно закодированной целью запроса (request-target). Получателю НЕ СЛЕДУЕТ пытаться выполнить автозамену, а затем обработать запрос без перенаправления, поскольку недопустимая строка запроса может быть специально создана для обхода фильтров безопасности в цепочке запросов.

HTTP не устанавливает предопределенное ограничение на длину строки запроса, как описано в разделе 2.5. Сервер, который получает метод более длинный, чем любой, который он реализует, ДОЛЖЕН ответить кодом состояния 501 (не реализовано). Сервер, который получает целевой запрос дольше, чем любой URI, который он хочет проанализировать, ДОЛЖЕН ответить кодом состояния 414 (слишком длинный URI) (см. Раздел 6.5.12 [RFC7231 #]).

На практике встречаются различные специальные ограничения на длину строки запроса. РЕКОМЕНДУЕТСЯ, чтобы все отправители и получатели HTTP поддерживали, как минимум, длину строки запроса в 8000 октетов.

3.1.2. Строка состояния (Status Line)

Первая строка ответного сообщения — это строка состояния (status-line), состоящая из версии протокола, пробела (SP), кода состояния, другого пробела, возможно пустой текстовой фразы, описывающей код состояния, и заканчивающейся CRLF.

status-line = HTTP-version SP status-code SP reason-phrase CRLF

Элемент «status-code» представляет собой трехзначный целочисленный код, описывающий результат попытки сервера понять и удовлетворить соответствующий запрос клиента. Остальная часть ответного сообщения должна интерпретироваться в свете семантики, определенной для этого кода состояния. См. Раздел 6 [RFC7231 #] для получения информации о семантике кодов состояния, включая классы кода состояния (обозначенного первой цифрой), коды состояния, определенные в этой спецификации, рекомендации по определению новых кодов состояния и IANA реестр.

status-code = 3DIGIT

Элемент reason-phrase (причина-фраза) существует с единственной целью предоставления текстового описания, связанного с числовым кодом состояния, в основном из уважения к более ранним протоколам интернет-приложений, которые чаще использовались с интерактивными текстовыми клиентами. Клиент ДОЛЖЕН игнорировать содержание фразы-причины.

reason-phrase = *( HTAB / SP / VCHAR / obs-text )

3.2. Поля заголовка

Каждое поле заголовка состоит из нечувствительного к регистру имени поля, за которым следует двоеточие («:»), необязательный начальный пробел, значение поля и необязательный конечный пробел.

header-field = field-name ":" OWS field-value OWS

field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text

obs-fold = CRLF 1*( SP / HTAB )
; устаревшая линия складывания
; смотри Раздел 3.2.4

Маркер имени поля помечает соответствующее значение поля как семантику, определенную этим полем заголовка. Например, поле заголовка Date определено в разделе 7.1.1.2 [RFC7231 #] как содержащее временную метку происхождения для сообщения, в котором оно появляется.

3.2.1. Расширяемость поля

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

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

Прокси-сервер ДОЛЖЕН пересылать нераспознанные поля заголовка, если только имя поля не указано в поле заголовка Connection (раздел 6.1) или прокси-сервер специально не настроен для блокировки или иного преобразования таких полей. Другие получатели ДОЛЖНЫ игнорировать нераспознанные поля заголовка. Эти требования позволяют расширять функциональность HTTP, не требуя предварительного обновления развернутых посредников.

Все определенные поля заголовков должны быть зарегистрированы в IANA в реестре «Заголовки сообщений», как описано в разделе 8.3 [RFC7231 #].

3.2.2. Порядок полей

Порядок получения полей заголовков с разными именами не имеет значения. Однако рекомендуется сначала отправлять поля заголовка, которые содержат управляющие данные, такие как «Host по запросам» и «Date по ответам», чтобы реализации могли решить, когда не следует обрабатывать сообщение как можно раньше. Сервер НЕ ДОЛЖЕН применять запрос к целевому ресурсу до тех пор, пока не будет получен весь раздел заголовка запроса, поскольку более поздние поля заголовка могут включать условия, учетные данные аутентификации или намеренно вводить в заблуждение дублирующие поля заголовка, которые могут повлиять на обработку запроса.

Отправитель НЕ ДОЛЖЕН генерировать несколько полей заголовка с одним и тем же именем поля в сообщении, если только все значение поля для этого поля заголовка не определено как список, разделенный запятыми [т.е. # (значения)], или поле заголовка не является известное исключение (как отмечено ниже).

Получатель МОЖЕТ объединить несколько полей заголовка с одним и тем же именем поля в одну пару «field-name: field-value«, не изменяя семантику сообщения, добавляя каждое последующее значение поля в объединенное значение поля по порядку, разделяя их запятой. Порядок, в котором принимаются поля заголовка с одинаковым именем поля, имеет значение для интерпретации значения объединенного поля; прокси НЕ ДОЛЖЕН изменять порядок значений этих полей при пересылке сообщения.

Примечание. На практике поле заголовка «Set-Cookie» ([RFC6265 #]) часто появляется в ответном сообщении несколько раз и не использует синтаксис списка, нарушая вышеуказанные требования для нескольких полей заголовка с одним и тем же именем. Поскольку его нельзя объединить в одно значение поля, получатели должны обрабатывать «Set-Cookie» как особый случай при обработке полей заголовка. (Подробнее см. Приложение A.2.3 [Kri2001].)

3.2.3. Пробелы

Эта спецификация использует три правила для обозначения использования линейного пробела:

  • OWS (необязательный пробел — optional whitespace)
  • RWS (обязательный пробел — required whitespace)
  • BWS («плохой» пробел — «bad» whitespace)

Правило OWS используется там, где могут появиться ноль или более линейных октетов. Для элементов протокола, где необязательный пробел предпочтительнее для улучшения читабельности, отправителю СЛЕДУЕТ генерировать необязательный пробел в виде одного SP; в противном случае отправителю НЕ СЛЕДУЕТ генерировать необязательные пробелы, кроме случаев, когда это необходимо для исключения недопустимых или нежелательных элементов протокола во время фильтрации сообщений на месте.

Правило RWS используется, когда для разделения токенов поля требуется хотя бы один линейный октет пробела. Отправителю СЛЕДУЕТ генерировать RWS как один SP.

Правило BWS используется, когда грамматика допускает необязательные пробелы только по историческим причинам. Отправитель НЕ ДОЛЖЕН генерировать BWS в сообщениях. Получатель ДОЛЖЕН проанализировать такие плохие пробелы и удалить их, прежде чем интерпретировать элемент протокола.

OWS = *( SP / HTAB ) ; optional whitespace
RWS = 1*( SP / HTAB ) ; required whitespace
BWS = OWS ; "bad" whitespace

3.2.4. Полевой анализ (Синтаксический анализ поля)

Сообщения анализируются с использованием общего алгоритма, независимого от отдельных имен полей заголовка. Содержимое в данном значении поля не анализируется до более поздней стадии интерпретации сообщения (обычно после обработки всего раздела заголовка сообщения). Следовательно, эта спецификация не использует правила ABNF для определения каждой пары «Field-Name: Field Value» (Имя поля: Значение поля), как это было сделано в предыдущих выпусках. Вместо этого в данной спецификации используются правила ABNF, которые именуются в соответствии с каждым зарегистрированным именем поля, причем правило определяет действительную грамматику для соответствующих значений поля этого поля (т. е. После того, как значение поля было извлечено из раздела заголовка универсальным синтаксическим анализатором поля).

Не допускается никаких пробелов между именем поля заголовка и двоеточием. В прошлом различия в обработке таких пробелов приводили к уязвимостям безопасности при маршрутизации запросов и обработке ответов. Сервер ДОЛЖЕН отклонить любое полученное сообщение запроса, которое содержит пробел между именем поля заголовка и двоеточием с кодом ответа 400 (неправильный запрос). Прокси-сервер ДОЛЖЕН удалить все такие пробелы из ответного сообщения перед пересылкой сообщения в нисходящем направлении.

Значению поля может предшествовать и/или следовать необязательный пробел (OWS); одиночный SP, предшествующий значению поля, предпочтителен для постоянной читабельности человеком. Значение поля не содержит начальных или конечных пробелов: OWS, возникающие перед первым не пропущенным октетом значения поля или после последнего непробельного октета значения поля, должны быть исключены анализаторами при извлечении значения поля из поле заголовка

Исторически значения полей заголовка HTTP могли быть расширены на несколько строк путем добавления каждой дополнительной строки по крайней мере к одному пробелу или горизонтальной табуляции (obs-fold). Эта спецификация не поддерживает такое свертывание строк, кроме как в типе носителя «message/http» (Раздел 8.3.1). Отправитель НЕ ДОЛЖЕН генерировать сообщение, которое включает в себя перенос строки (т. е. Имеет любое значение поля, которое соответствует правилу obs-fold), если только сообщение не предназначено для упаковки в типе «message/http».

Сервер, который получает obs-fold в сообщении запроса, которое не находится в контейнере «message/http», ДОЛЖЕН либо отклонить сообщение, отправив 400 (неверный запрос), предпочтительно с представлением, объясняющим, что устаревшее сворачивание строки недопустимо, либо заменить каждый получен obs-fold с одним или несколькими октетами SP перед интерпретацией значения поля или пересылкой сообщения в нисходящем направлении.

Прокси-сервер или шлюз, который получает помехи в ответном сообщении, находящемся вне контейнера «message/http», ДОЛЖЕН либо отбросить сообщение и заменить его ответом 502 (плохой шлюз), предпочтительно с представлением, объясняющим, что недопустимое свертывание строк было получено, или замените каждый полученный obs-fold на один или несколько октетов SP перед интерпретацией значения поля или пересылкой сообщения в нисходящем направлении.

Пользовательский агент, который получает «obs-fold» в ответном сообщении, которое находится не в контейнере «message/http», ДОЛЖЕН заменить каждый полученный «obs-fold» на один или несколько октетов SP перед интерпретацией значения поля.

Исторически HTTP разрешал содержимое полей с текстом в кодировке ISO-8859-1 [ISO-8859-1], поддерживая другие кодировки только с использованием кодировки [RFC2047 #]. На практике большинство значений полей заголовка HTTP используют только подмножество набора символов US-ASCII [USASCII]. Вновь определенные поля заголовка ДОЛЖНЫ ограничивать свои значения полей октетами US-ASCII. Получатель ДОЛЖЕН трактовать другие октеты в содержимом поля (obs-text) как непрозрачные данные.

3.2.5. Пределы поля

HTTP не устанавливает предопределенного ограничения на длину каждого поля заголовка или на длину раздела заголовка в целом, как описано в разделе 2.5. На практике встречаются различные специальные ограничения на длину отдельного поля заголовка, часто в зависимости от конкретной семантики поля.

Сервер, который получает поле заголовка запроса или набор полей, больше, чем он хочет обработать, ДОЛЖЕН ответить соответствующим кодом состояния 4xx (Ошибка клиента). Игнорирование таких полей заголовка увеличит уязвимость сервера для запроса атак контрабанды (раздел 9.5).

Клиент МОЖЕТ отбросить или усечь полученные поля заголовка, которые больше, чем клиент желает обработать, если семантика поля такова, что отброшенные значения могут быть безопасно проигнорированы без изменения рамок сообщения или семантики ответа.

3.2.6. Компоненты значения поля

Большинство значений полей заголовка HTTP определяются с использованием общих компонентов синтаксиса (токен, строка в кавычках и комментарий), разделенных пробелами или определенными символами-разделителями. Разделители выбираются из набора визуальных символов US-ASCII, которые не допускаются в токене (DQUOTE и «(),/:;<=>?@[\]{}»).

token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "’" / "*"
/ "+" / "-" / "." / "^" / "_" / "‘" / "|" / "~"
/ DIGIT / ALPHA
; любой VCHAR, кроме разделителей

Текстовая строка анализируется как одно значение, если она заключена в двойные кавычки.

quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
obs-text = %x80-FF

Комментарии могут быть включены в некоторые поля заголовка HTTP, заключив текст комментария в круглые скобки. Комментарии допускаются только в полях, содержащих «comment» (комментарий) как часть определения значения их поля.

comment = "(" *( ctext / quoted-pair / comment ) ")"
ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text

Октет с обратной косой чертой («\») можно использовать как механизм цитирования с одним октетом в конструкциях строк цитирования и комментариев. Получатели, которые обрабатывают значение строки в кавычках, ДОЛЖНЫ обрабатывать пару в кавычках, как если бы она была заменена октетом после обратной косой черты.

quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )

Отправителю НЕ СЛЕДУЕТ генерировать «quoted-pair«(пару в кавычках) в  «quoted-string«(строке в кавычках), за исключением случаев, когда необходимо заключить в кавычки октеты DQUOTE и обратный слеш, встречающиеся в этой строке. Отправителю НЕ СЛЕДУЕТ генерировать quoted-pair (пару в кавычках) в comment (комментарии), за исключением случаев, когда необходимо заключить в кавычки круглые скобки [«(» и «)»] и октеты обратной косой черты, встречающиеся в этом комментарии.

3.3. Тело сообщения (Message Body)

Тело сообщения (если оно есть) из HTTP-сообщения используется для переноса тела полезной нагрузки этого запроса или ответа. Тело сообщения идентично телу полезной нагрузки, если только не было применено кодирование передачи, как описано в разделе 3.3.1.

message-body = *OCTET

Правила, когда тело сообщения разрешено в сообщении, различаются для запросов и ответов.

Присутствие тела сообщения в запросе сигнализируется полем заголовка «Content-Length» или «Transfer-Encoding». Кадрирование сообщения запроса не зависит от семантики метода, даже если метод не определяет какого-либо использования для тела сообщения.

Наличие тела сообщения в ответе зависит как от метода запроса, на который он отвечает, так и от кода состояния ответа (раздел 3.1.2). Ответы на метод запроса HEAD (раздел 4.3.2 [RFC7231 #]) никогда не включают в себя тело сообщения, поскольку соответствующие поля заголовка ответа (например, Transfer-Encoding, Content-Length и т. д.), если присутствует, указывает только то, что их значения были бы, если бы метод запроса был GET (Раздел 4.3.1 [RFC7231 #]). 2xx (успешные) ответы на метод запроса CONNECT (раздел 4.3.6 [RFC7231 #]) переключаются в туннельный режим вместо того, чтобы иметь тело сообщения. Все ответы 1xx (информационный), 204 (без содержимого) и 304 (без изменений) не содержат тела сообщения. Все остальные ответы включают тело сообщения, хотя тело может иметь нулевую длину.

3.3.1. Заголовок «Transfer-Encoding»

В поле заголовка «Transfer-Encoding» перечислены имена кодирования передачи, соответствующие последовательности кодировок передачи, которые были (или будут) применены к телу полезной нагрузки для формирования тела сообщения. Кодировки перевода определены в разделе 4.

Transfer-Encoding = 1#transfer-coding

«Transfer-Encoding» является аналогом поля «Content-Transfer-Encoding» в MIME, которое было разработано для обеспечения безопасной передачи двоичных данных через 7-битную транспортную службу ([RFC2045 #], раздел 6). Тем не менее, безопасный транспорт имеет другую направленность для 8-битного чистого протокола передачи. В случае HTTP Transfer-Encoding в первую очередь предназначен для точного разграничения динамически генерируемой полезной нагрузки и для различения кодировок полезной нагрузки, которые применяются только для эффективности или безопасности транспорта, и тех, которые являются характеристиками выбранного ресурса.

Получатель ДОЛЖЕН иметь возможность анализировать фрагментированное (chunked) кодирование передачи (раздел 4.1), поскольку оно играет решающую роль в формировании сообщений, когда размер тела полезной нагрузки заранее не известен. Отправитель НЕ ДОЛЖЕН применять фрагментирование более одного раза к телу сообщения (т. е. фрагментирование уже фрагментированного сообщения не допускается). Если какое-либо кодирование передачи, отличное от фрагментирования, применяется к телу полезной нагрузки запроса, отправитель ДОЛЖЕН применить фрагментирование (chunked) в качестве окончательного кодирования передачи, чтобы гарантировать, что сообщение правильно оформлено. Если какое-либо кодирование передачи, отличное от chunked, применяется к телу полезной нагрузки ответа, отправитель ДОЛЖЕН либо применить фрагментирование (chunked) в качестве окончательного кодирования передачи, либо завершить сообщение, закрыв соединение.

Например,

Transfer-Encoding: gzip, chunked

указывает, что тело полезной нагрузки было сжато с использованием gzip-кодирования, а затем разделено на части с использованием chunked-кодирования при формировании тела сообщения.

В отличие от «Content-Encoding» (раздел 3.1.2.1 [RFC7231 #]), «Transfer-Encoding» является свойством сообщения, а не представления, и любой получатель в цепочке запросов/ответов МОЖЕТ декодировать полученные код(ы) передачи или применять дополнительное кодирование(я) передачи в тело сообщения, предполагая, что соответствующие изменения внесены в значение поля «Transfer-Encoding». Дополнительная информация о параметрах кодирования может быть предоставлена другими полями заголовка, не определенными в этой спецификации.

«Transfer-Encoding» (Кодирование передачи) МОЖЕТ быть отправлено в ответе на запрос HEAD или в ответе 304 (не изменен) (раздел 4.1 [RFC7232 #]) на запрос GET, ни один из которых не содержит тела сообщения, чтобы указать, что исходный сервер будет применили код передачи к телу сообщения, если запрос был безусловным GET. Однако это указание не требуется, поскольку любой получатель в цепочке ответов (включая исходный сервер) может удалить кодировки передачи, когда они не нужны.

Сервер НЕ ДОЛЖЕН отправлять поле заголовка «Transfer-Encoding» в любом ответе с кодом состояния 1xx (информационный) или 204 (без содержимого). Сервер НЕ ДОЛЖЕН отправлять поле заголовка «Transfer-Encoding» в любом ответе 2xx (успешно) на запрос CONNECT (раздел 4.3.6 [RFC7231 #]).

Transfer-Encoding был добавлен в HTTP/1.1. Обычно предполагается, что реализации, рекламирующие только поддержку HTTP/1.0, не поймут, как обрабатывать кодированные данные передачи. Клиент НЕ ДОЛЖЕН отправлять запрос, содержащий Transfer-Encoding, если он не знает, что сервер будет обрабатывать HTTP/1.1 (или более поздние) запросы; такие знания могут быть в форме конкретной пользовательской конфигурации или путем запоминания версии ранее полученного ответа. Сервер НЕ ДОЛЖЕН отправлять ответ, содержащий Transfer-Encoding, если соответствующий запрос не указывает HTTP/1.1 (или более позднюю версию).

Сервер, который получает сообщение запроса с кодировкой передачи, которую он не понимает, ДОЛЖЕН ответить 501 (не реализовано).

3.3.2. Content-Length

Когда сообщение не имеет поля заголовка Transfer-Encoding, поле заголовка Content-Length может предоставить ожидаемый размер в виде десятичного числа октетов для потенциального тела полезной нагрузки. Для сообщений, которые содержат тело полезной нагрузки, значение поля Content-Length предоставляет информацию об кадре, необходимую для определения того, где заканчивается тело (и сообщение). Для сообщений, которые не включают тело полезной нагрузки, Content-Length указывает размер выбранного представления (Раздел 3 [RFC7231 #]).

Content-Length = 1*DIGIT

Примером является

Content-Length: 3495

Отправитель НЕ ДОЛЖЕН отправлять поле заголовка Content-Length ни в одном сообщении, которое содержит поле заголовка Transfer-Encoding.

Пользовательский агент ДОЛЖЕН отправить Content-Length в сообщении запроса, когда не передано Transfer-Encoding и метод запроса определяет значение для вложенного тела полезной нагрузки. Например, поле заголовка Content-Length обычно отправляется в запросе POST, даже если значение равно 0 (указывает на пустое тело полезной нагрузки). Пользовательский агент НЕ ДОЛЖЕН отправлять поле заголовка Content-Length, если сообщение запроса не содержит тела полезной нагрузки, а семантика метода не ожидает такого тела.

Сервер МОЖЕТ отправить поле заголовка Content-Length в ответ на запрос HEAD (раздел 4.3.2 [RFC7231 #]); сервер НЕ ДОЛЖЕН отправлять Content-Length в таком ответе, если его значение поля не равно десятичному числу октетов, которое было бы отправлено в теле полезной нагрузки ответа, если бы тот же запрос использовал метод GET.

Сервер МОЖЕТ отправить поле заголовка Content-Length в ответе 304 (не изменено) на условный запрос GET (раздел 4.1 [RFC7232 #]); сервер НЕ ДОЛЖЕН отправлять Content-Length в таком ответе, если его значение поля не равно десятичному числу октетов, которое было бы отправлено в теле полезной нагрузки ответа 200 (ОК) на тот же запрос.

Сервер НЕ ДОЛЖЕН отправлять поле заголовка Content-Length в любом ответе с кодом состояния 1xx (информационный) или 204 (без содержимого). Сервер НЕ ДОЛЖЕН отправлять поле заголовка Content-Length в любом ответе 2xx (успешно) на запрос CONNECT (раздел 4.3.6 [RFC7231 #]).

Помимо случаев, определенных выше, при отсутствии Transfer-Encoding сервер происхождения ДОЛЖЕН отправить поле заголовка Content-Length, когда размер тела полезной нагрузки известен до отправки полного раздела заголовка. Это позволит нижестоящим получателям измерить ход передачи, узнать, когда полученное сообщение завершено, и потенциально повторно использовать соединение для дополнительных запросов.

Любое значение поля Content-Length, большее или равное нулю, является действительным. Поскольку не существует заранее определенного предела для длины полезной нагрузки, получатель ДОЛЖЕН предвидеть потенциально большие десятичные цифры и предотвращать ошибки синтаксического анализа из-за переполнения целочисленных преобразований (Раздел 9.3).

Если получено сообщение с несколькими полями заголовка Content-Length со значениями поля, состоящими из одного и того же десятичного значения, или одно поле заголовка Content-Length со значением поля, содержащим список идентичных десятичных значений (например, «Content-Length: 42, 42»), указывая, что дубликаты полей заголовка Content-Length были сгенерированы или объединены обработчиком сообщений восходящего направления, тогда получатель ДОЛЖЕН либо отклонить сообщение как недействительное, либо заменить дублированные значения полей одним действительным полем Content-Length, содержащим это десятичное значение до определения длины тела сообщения или пересылки сообщения.

Примечание. Использование HTTP Content-Length для формирования сообщений существенно отличается от использования того же поля в MIME, где это необязательное поле, используемое только в медиа-типе «message/external-body».

3.3.3. Длина тела сообщения

Длина тела сообщения определяется одним из следующих (в порядке приоритета):

1. Любой ответ на запрос HEAD и любой ответ с кодом состояния 1xx (информационный), 204 (без содержимого) или 304 (не измененный) всегда завершается первой пустой строкой после полей заголовка, независимо от полей заголовка присутствует в сообщении и, следовательно, не может содержать тело сообщения.

2. Любой 2xx (успешный) ответ на запрос CONNECT подразумевает, что соединение станет туннелем сразу после пустой строки, которая завершает поля заголовка. Клиент ДОЛЖЕН игнорировать любые поля заголовка Content-Length или Transfer-Encoding, полученные в таком сообщении.

3. Если присутствует поле заголовка Transfer-Encoding и кодирование передачи по частям (Раздел 4.1) является окончательным кодированием, длина тела сообщения определяется путем считывания и декодирования данных по частям, пока кодирование передачи не покажет, что данные завершены.

Если в заголовке присутствует поле заголовка Transfer-Encoding, а кодирование передачи по частям не является окончательным кодированием, длина тела сообщения определяется путем считывания соединения, пока оно не будет закрыто сервером. Если поле заголовка Transfer-Encoding присутствует в запросе, и кодирование передачи по частям не является окончательным кодированием, длина тела сообщения не может быть надежно определена; сервер ДОЛЖЕН ответить кодом состояния 400 (неверный запрос), а затем закрыть соединение.

Если сообщение получено с полем заголовка Transfer-Encoding и Content-Length, Transfer-Encoding переопределяет Content-Length. Такое сообщение может указывать на попытку выполнить контрабанду запроса (раздел 9.5) или разбиение ответа (раздел 9.4) и должно рассматриваться как ошибка. Отправитель ДОЛЖЕН удалить полученное поле Content-Length до пересылки такого сообщения в нисходящем направлении.

4. Если сообщение получено без Transfer-Encoding и с несколькими полями заголовка Content-Length, имеющими разные значения поля, или с одним полем заголовка Content-Length, имеющим недопустимое значение, то кадрирование сообщения является недействительным, и получатель ДОЛЖЕН обработать его как неисправимую ошибку. Если это сообщение с запросом, сервер ДОЛЖЕН ответить кодом состояния 400 (неверный запрос), а затем закрыть соединение. Если это ответное сообщение, полученное прокси-сервером, прокси-сервер ДОЛЖЕН закрыть соединение с сервером, отбросить полученный ответ и отправить клиенту ответ 502 (Bad Gateway). Если это ответное сообщение, полученное пользовательским агентом, пользовательский агент ДОЛЖЕН закрыть соединение с сервером и отбросить полученный ответ.

5. Если допустимое поле заголовка Content-Length присутствует без Transfer-Encoding, его десятичное значение определяет ожидаемую длину тела сообщения в октетах. Если отправитель закрывает соединение или тайм-аут получателя до получения указанного количества октетов, получатель ДОЛЖЕН считать сообщение неполным и закрыть соединение.

6. Если это сообщение запроса и ни одно из вышеперечисленного не соответствует действительности, тогда длина тела сообщения равна нулю (тело сообщения отсутствует).

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

Поскольку не существует способа отличить успешно завершенное сообщение с разделителями в близких пределах от частично принятого сообщения, прерванного из-за сбоя в сети, сервер ДОЛЖЕН генерировать сообщения кодирования или сообщения с разделителями по длине, когда это возможно. Функция близкого разграничения существует главным образом для обратной совместимости с HTTP/1.0.

Сервер МОЖЕТ отклонить запрос, который содержит тело сообщения, но не Content-Length, ответив 411 (длина обязательна).

Если кодирование передачи, отличное от chunked (фрагментированный), не было применено, клиенту, который отправляет запрос, содержащий тело сообщения, СЛЕДУЕТ использовать действительное поле заголовка Content-Length, если длина тела сообщения известна заранее, а не кодирование передачи chunked (фрагментированный), поскольку некоторые существующие службы отвечают на фрагментирование с помощью кода состояния 411 (длина обязательна), даже если они понимают кодирование передачи chunked. Обычно это происходит потому, что такие сервисы реализуются через шлюз, которому требуется длина контента перед вызовом, а сервер не может или не хочет буферизовать весь запрос перед обработкой.

Пользовательский агент, который отправляет запрос, содержащий тело сообщения, ДОЛЖЕН отправить действительное поле заголовка Content-Length, если он не знает, что сервер будет обрабатывать HTTP/1.1 (или более поздние) запросы; такие знания могут быть в форме конкретной пользовательской конфигурации или путем запоминания версии ранее полученного ответа.

Если окончательный ответ на последний запрос по соединению был полностью получен и остаются дополнительные данные для чтения, пользовательский агент МОЖЕТ отбросить оставшиеся данные или попытаться определить, принадлежат ли эти данные как часть предыдущего тела ответа, что может быть случай, если значение Content-Length предыдущего сообщения является неправильным. Клиент НЕ ДОЛЖЕН обрабатывать, кэшировать или пересылать такие дополнительные данные в качестве отдельного ответа, поскольку такое поведение будет уязвимо для заражения кэша.

3.4. Обработка неполных сообщений

Сервер, который получает сообщение о неполном запросе, как правило, из-за отмененного запроса или исключительной ситуации, вызванной тайм-аутом, МОЖЕТ отправить сообщение об ошибке до закрытия соединения.

Клиент, который получает сообщение с неполным ответом, которое может произойти, если соединение преждевременно закрыто или при неудачном декодировании предположительно фрагментированного кодирования передачи, ДОЛЖНО записать сообщение как неполное. Требования к кэшу для неполных ответов определены в разделе 3 [RFC7234 #].

Если ответ заканчивается в середине раздела заголовка (до получения пустой строки) и код состояния может полагаться на поля заголовка для передачи полного значения ответа, тогда клиент не может предположить, что значение было передано; клиенту может потребоваться повторить запрос, чтобы определить, какое действие предпринять дальше.

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

3.5. Надежность синтаксического анализа сообщения

Более старые реализации пользовательских агентов HTTP/1.0 могли отправлять дополнительный CRLF после запроса POST в качестве обходного пути для некоторых ранних серверных приложений, которые не могли прочитать содержимое тела сообщения, которое не было завершено окончанием строки. Пользовательский агент HTTP/1.1 НЕ ДОЛЖЕН предшествовать или следовать запросу с дополнительным CRLF. Если желательно завершить тело сообщения запроса окончанием строки, то пользовательский агент ДОЛЖЕН считать октеты CRLF завершения как часть длины тела сообщения.

В интересах надежности, сервер, который ожидает получить и проанализировать строку запроса, ДОЛЖЕН игнорировать хотя бы одну пустую строку (CRLF), полученную до строки запроса.

Хотя терминатор строки для полей начальной строки и заголовка является последовательностью CRLF, получатель МОЖЕТ распознавать один LF как терминатор строки и игнорировать любой предшествующий CR.

Хотя правила грамматики строки запроса и строки состояния требуют, чтобы каждый элемент компонента был разделен одним октетом SP, получатели МОГУТ вместо этого анализировать границы слов, разделенные пробелами, и, кроме терминатора CRLF, рассматривать любую форму пробелов как разделитель SP при игнорировании предшествующего или конечного пробела; такой пробел включает в себя один или несколько следующих октетов: SP, HTAB, VT (% x0B), FF (% x0C) или пустой CR. Однако мягкий анализ может привести к уязвимостям безопасности, если есть несколько получателей сообщения, и у каждого своя уникальная интерпретация надежности (см. Раздел 9.5).

Когда сервер, прослушивающий только сообщения HTTP-запроса или обрабатывающий то, что из начальной строки выглядит как сообщение HTTP-запроса, получает последовательность октетов, которая не соответствует грамматике HTTP-сообщения, кроме исключений надежности, перечисленных выше, сервер ДОЛЖЕН ответить 400 (неправильный запрос).

4. Передача кодирований

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

transfer-coding = "chunked" ; Раздел 4.1
/ "compress" ; Раздел 4.2.1
/ "deflate" ; Раздел 4.2.2
/ "gzip" ; Раздел 4.2.3
/ transfer-extension
transfer-extension = token *( OWS ";" OWS transfer-parameter )

Параметры представлены в форме пары «name» или «name=value».

transfer-parameter = token BWS "=" BWS ( token / quoted-string )

Все имена кодирования передачи нечувствительны к регистру и должны быть зарегистрированы в реестре HTTP Transfer Coding, как определено в разделе 8.4. Они используются в полях заголовка TE (раздел 4.3) и Transfer-Encoding (раздел 3.3.1).

4.1. Поблочная передача кодирования (Chunked Transfer Coding)

Кодирование передачи по блокам (chunked transfer coding) оборачивает тело полезной нагрузки, чтобы передать его в виде серии кусков, каждый со своим собственным индикатором размера, за которым следует НЕОБЯЗАТЕЛЬНЫЙ трейлер, содержащий поля заголовка. «Chunked» позволяет передавать потоки контента неизвестного размера в виде последовательности буферов с разделителями по длине, что позволяет отправителю сохранять постоянство соединения, а получателю знать, когда он получил все сообщение.

chunked-body = *chunk
last-chunk
trailer-part
CRLF


chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF
chunk-size = 1*HEXDIG
last-chunk = 1*("0") [ chunk-ext ] CRLF


chunk-data = 1*OCTET ; a sequence of chunk-size octets

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

Получатель ДОЛЖЕН иметь возможность анализировать и декодировать фрагментированное кодирование передачи.

4.1.1. Расширения блока (Chunk Extensions)

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

chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string

Кодирование по частям специфично для каждого соединения и, вероятно, будет удалено или перекодировано каждым получателем (включая посредников), прежде чем любое приложение более высокого уровня сможет проверить расширения. Следовательно, использование расширений чанка (блока) обычно ограничивается специализированными службами HTTP, такими как «long polling» (длительный опрос) (когда клиент и сервер могут иметь общие ожидания относительно использования расширений чанка) или для заполнения в сквозном защищенном соединении.

Получатель ДОЛЖЕН игнорировать нераспознанные расширения чанков. Сервер должен ограничить общую длину расширений чанков, полученных в запросе, разумной суммой для предоставляемых услуг, так же, как он применяет ограничения длины и таймауты для других частей сообщения, и генерировать соответствующий 4xx (Ошибка клиента ) ответ, если эта сумма превышена.

4.1.2. Поблочная часть трейлера

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

trailer-part = *( header-field CRLF )

Отправитель НЕ ДОЛЖЕН генерировать трейлер, который содержит поле, необходимое для формирования кадра сообщения (например, Transfer-Encoding и Content-Length), маршрутизации (например, хоста), модификаторов запроса (например, элементов управления и условий в Разделе 5 [RFC7231 #]) аутентификация (например, см. [RFC7235 #] и [RFC6265 #]), данные управления ответом (например, см. раздел 7.1 в [RFC7231 #]) или определение способа обработки полезной нагрузки (например, Content-Encoding, Content-Type, Content- Рейндж и трейлер).

При получении фрагментированного сообщения, содержащего непустой трейлер, получатель МОЖЕТ обработать поля (кроме тех, которые запрещены выше), как если бы они были добавлены в раздел заголовка сообщения. Получатель ДОЛЖЕН игнорировать (или рассматривать как ошибку) любые поля, которые запрещено отправлять в трейлере, поскольку обработка их так, как если бы они присутствовали в разделе заголовка, могла бы обойти внешние фильтры безопасности.

Если запрос не включает поле заголовка TE, указывающее, что «трейлеры» являются приемлемыми, как описано в Разделе 4.3, серверу НЕ СЛЕДУЕТ генерировать поля трейлера, которые, по его мнению, необходимы для приема пользовательским агентом. Без TE, содержащего «трейлеры», сервер должен предполагать, что поля трейлера могут быть незаметно отброшены по пути к пользовательскому агенту. Это требование позволяет посредникам пересылать разорванное сообщение получателю HTTP/1.0 без буферизации всего ответа.

4.1.3. Поблочное декодирование

Процесс декодирования фрагментированного кодирования передачи может быть представлен в псевдокоде как:

length := 0
read chunk-size, chunk-ext (if any), and CRLF
while (chunk-size > 0) {
   read chunk-data and CRLF
   append chunk-data to decoded-body
   length := length + chunk-size
   read chunk-size, chunk-ext (if any), and CRLF
}
read trailer field
while (trailer field is not empty) {
   if (trailer field is allowed to be sent in a trailer) {
      append trailer field to existing header fields
   }
   read trailer-field
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
Remove Trailer from existing header fields

4.2. Компрессионное кодирование (Кодировки сжатия)

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

4.2.1. Сжатое кодирование (Compress Coding)

Кодирование «compress» — это адаптивное кодирование Lempel-Ziv-Welch (LZW) [Welch], которое обычно создается программой сжатия файлов UNIX «compress». Получателю СЛЕДУЕТ считать «x-compress» эквивалентным «compress».

4.2.2. Опровержение кодирования (Deflate Coding)

Кодирование «deflate» — это формат данных «zlib» [RFC1950 #], содержащий поток сжатых данных «deflate» [RFC1951 #], в котором используется комбинация алгоритма сжатия Lempel-Ziv (LZ77) и кодирования Хаффмана.

Примечание. Некоторые несовместимые реализации отправляют сжатые данные «deflate» без оболочки zlib.

4.2.3. Gzip кодирование

Кодирование «gzip» — это кодирование LZ77 с 32-битной проверкой циклического избыточного кода (CRC), которое обычно создается программой сжатия файлов gzip [RFC1952 #]. Получатель ДОЛЖЕН считать «x-gzip» эквивалентным «gzip».

4.3. Поле заголовка TE

Поле заголовка «TE» в запросе указывает, какие кодировки передачи, кроме chunked, клиент готов принять в ответ, и желает ли клиент принять поля трейлера в кодировании переноса.

Значение поля «TE» состоит из списка разделенных запятыми имен кодирования передачи, каждое из которых допускает необязательные параметры (как описано в разделе 4), и / или ключевое слово «trailers» (трейлеры). Клиент НЕ ДОЛЖЕН отправлять название кодированной передачи в TE; chunked всегда приемлем для получателей HTTP/1.1.

TE = #t-codings
t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
t-ranking = OWS ";" OWS "q=" rank
rank = ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] )

Три примера из нас ниже.

TE: deflate
TE:
TE: trailers, deflate;q=0.5

Наличие ключевого слова «trailers» (трейлеры) указывает на то, что клиент готов принять поля трейлера в кодировке передачи по частям, как определено в разделе 4.1.2, от своего имени и любых последующих клиентов. Для запросов от посредника это означает, что:

  • (a) все последующие клиенты готовы принять поля трейлера в переадресованном ответе; или
  • (b) посредник попытается буферизовать ответ от имени нижестоящих получателей.

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

Когда допустимы множественные кодировки передачи, клиент МОЖЕТ ранжировать кодировки по предпочтению, используя нечувствительный к регистру параметр «q» (аналогично значениям q, используемым в полях согласования контента, раздел 5.3.1 [RFC7231 #]). Значение ранга представляет собой действительное число в диапазоне от 0 до 1, где 0,001 является наименее предпочтительным, а 1 является наиболее предпочтительным; значение 0 означает «not acceptable» (не приемлемо).

Если значение поля «TE» пусто или поле «TE» отсутствует, то применяется только приемлемое кодирование передачи. Сообщение без кодировки передачи всегда приемлемо.

Поскольку поле заголовка «TE» применяется только к непосредственному соединению, отправитель «TE» ДОЛЖЕН также отправить опцию подключения «TE» в поле заголовка Connection (раздел 6.1), чтобы предотвратить пересылку поля «TE» посредниками, которые не поддерживают его семантика.

4.4. Трейлер (Trailer)

Когда сообщение включает в себя тело сообщения, закодированное с помощью фрагментированной кодировки передачи, и отправитель желает отправить метаданные в виде полей трейлера в конце сообщения, отправителю СЛЕДУЕТ создать поле заголовка трейлера перед телом сообщения, чтобы указать, какие поля будут присутствовать в трейлерах. Это позволяет получателю подготовиться к получению этих метаданных до того, как он начнет обрабатывать тело, что полезно, если сообщение передается в потоковом режиме и получатель желает подтвердить проверку целостности на лету.

Trailer = 1#field-name

5. Маршрутизация сообщений (Message Routing)

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

5.1. Определение целевого ресурса

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

HTTP-связь инициируется пользовательским агентом для некоторой цели. Цель — это комбинация семантики запросов, которые определены в [RFC7231 #], и целевой ресурс, к которому применяется эта семантика. Ссылка на URI (раздел 2.7) обычно используется в качестве идентификатора для «target resource» (целевого ресурса), который пользовательский агент может преобразовать в абсолютную форму, чтобы получить «target URI» (целевой URI). Целевой URI исключает компонент фрагмента ссылки, если таковой имеется, поскольку идентификаторы фрагмента зарезервированы для обработки на стороне клиента ([RFC3986 #], раздел 3.5).

5.2. Подключение входящих (Connecting Inbound)

Как только целевой URI определен, клиент должен решить, нужен ли сетевой запрос для достижения желаемой семантики и, если да, куда этот запрос должен быть направлен.

Если у клиента есть кэш [RFC7234 #] и запрос может быть им удовлетворен, то запрос обычно направляется туда первым.

Если запрос не удовлетворен кешем, то типичный клиент проверит свою конфигурацию, чтобы определить, должен ли прокси использоваться для удовлетворения запроса. Конфигурация прокси зависит от реализации, но часто основывается на сопоставлении префиксов URI, выборочном сопоставлении прав доступа или обоих, а сам прокси обычно идентифицируется с помощью URI «http» или «https». Если прокси-сервер применим, клиент подключается к входящему, устанавливая (или повторно используя) соединение с этим прокси-сервером.

Если прокси-сервер не применим, типичный клиент вызывает процедуру-обработчик, обычно специфичную для схемы целевого URI, чтобы напрямую подключиться к органу управления целевым ресурсом. То, как это будет достигнуто, зависит от целевой схемы URI и определяется ее соответствующей спецификацией, подобно тому, как эта спецификация определяет доступ к серверу источника для разрешения «http» (раздел 2.7.1) и «https» (раздел 2.7.2) схем.

Требования HTTP относительно управления соединением определены в Разделе 6.

5.3. Запрос цели

Как только входящее соединение получено, клиент отправляет сообщение HTTP-запроса (Раздел 3) с целью запроса, полученной из целевого URI. Существует четыре различных формата для цели запроса, в зависимости от того, какой метод запрашивается, и от того, является ли запрос прокси-сервером.

request-target = origin-form
/ absolute-form
/ authority-form
/ asterisk-form

5.3.1. Исходная форма (origin-form)

Наиболее распространенной формой запроса-цели является форма-источник (origin-form).

origin-form = absolute-path [ "?" query ]

При выполнении запроса непосредственно к исходному серверу, кроме запроса CONNECT или общесерверного OPTIONS (как подробно описано ниже), клиент ДОЛЖЕН отправлять только абсолютный путь и компоненты запроса целевого URI в качестве запроса-цели. Если компонент пути целевого URI пуст, клиент ДОЛЖЕН отправить слэш «/» в качестве пути в исходной форме запроса-цели. Поле заголовка хоста также отправляется, как определено в разделе 5.4.

Например, клиент, желающий получить представление ресурса, идентифицированного как

http://www.example.org/where?q=now

непосредственно с исходного сервера откроет (или повторно использует) TCP-соединение с портом 80 хоста «www.example.org» и отправит строки:

GET /where?q=now HTTP/1.1
Host: www.example.org

с последующим остатком сообщения запроса.

5.3.2. Абсолютная форма (absolute-form)

При выполнении запроса к прокси-серверу, кроме запроса CONNECT или общесерверного OPTIONS (как подробно описано ниже), клиент ДОЛЖЕН отправить целевой URI в абсолютной форме (absolute-form) в качестве цели-запроса.

absolute-form = absolute-URI

Прокси-сервер запрашивает либо обслуживать этот запрос из действительного кэша, если это возможно, либо делать такой же запрос от имени клиента либо на следующий входящий прокси-сервер, либо непосредственно на исходный сервер, указанный целевым объектом запроса. Требования к такой «forwarding» (пересылке) сообщений определены в разделе 5.7.

Пример абсолютной формы строки запроса:

GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1

Чтобы разрешить переход к абсолютной форме для всех запросов в какой-либо будущей версии HTTP, сервер ДОЛЖЕН принимать абсолютную форму в запросах, даже если клиенты HTTP/1.1 будут отправлять их только в запросах к прокси.

5.3.3. Авторитетная форма (authority-form)

Полномочная форма (authority-form) целевых запросов (target-request) используется только для запросов CONNECT (раздел 4.3.6 [RFC7231 #]).

authority-form = authority

При выполнении запроса CONNECT для установления туннеля через один или несколько прокси, клиент ДОЛЖЕН отправить только целевой компонент URI (исключая любую информацию пользователя и его разделитель «@») в качестве цели запроса. Например,

CONNECT www.example.com:80 HTTP/1.1

5.3.4. Звездочная форма (asterisk-form)

Звездочная форма (asterisk-form) запроса-цели используется только для общесерверного запроса OPTIONS (раздел 4.3.7 [RFC7231 #]).

asterisk-form = "*"

Когда клиент желает запросить OPTIONS для сервера в целом, в отличие от определенного именованного ресурса этого сервера, клиент ДОЛЖЕН отправить только «*» (% x2A) в качестве цели запроса. Например,

OPTIONS * HTTP/1.1

Если прокси-сервер получает запрос OPTIONS с абсолютной формой запроса-цели, в котором URI имеет пустой путь и не имеет компонента запроса, то последний прокси в цепочке запросов ДОЛЖЕН послать цель-запроса «*» при пересылке запрос к указанному исходному серверу.

Например, запрос

OPTIONS http://www.example.org:8001 HTTP/1.1

будет перенаправлен окончательным прокси как

OPTIONS * HTTP/1.1
Host: www.example.org:8001

после подключения к порту 8001 хоста «www.example.org».

5.4. Поле заголовка Host

Поле заголовка «Host» в запросе предоставляет информацию о хосте и порте из целевого URI, позволяя серверу-источнику различать ресурсы при обслуживании запросов для нескольких имен хостов на одном IP-адресе.

Host = uri-host [ ":" port ] ; Раздел 2.7.1

Клиент ДОЛЖЕН отправить поле заголовка «Host» (узла) во всех сообщениях запроса HTTP/1.1. Если целевой URI включает в себя компонент полномочий authority, то клиент ДОЛЖЕН отправить значение поля для Host, идентичное этому компоненту полномочий authority, за исключением любого подкомпонента userinfo и его разделителя «@» (раздел 2.7.1). Если компонент полномочий authority отсутствует или не определен для целевого URI, тогда клиент ДОЛЖЕН отправить поле заголовка Host с пустым значением поля.

Поскольку значение поля Host является важной информацией для обработки запроса, пользовательский агент ДОЛЖЕН генерировать Host в качестве первого поля заголовка, следующего за строкой запроса.

Например, запрос методом GET к исходному серверу для

<http://www.example.org/pub/WWW/>

будет начинаться с:

GET /pub/WWW/ HTTP/1.1
Host: www.example.org

Клиент ДОЛЖЕН послать поле заголовка Host в запросе HTTP/1.1, даже если цель запроса (request-target) находится в абсолютной форме (absolute-form), поскольку это позволяет пересылать информацию о хосте через древние прокси-серверы HTTP/1.0, которые могли не реализовывать Host.

Когда прокси-сервер получает запрос с абсолютной формой запроса-цели, он ДОЛЖЕН игнорировать полученное поле заголовка Host (если оно есть) и вместо этого заменять его информацией о хосте цели-запроса. Прокси, который пересылает такой запрос, ДОЛЖЕН генерировать новое значение поля Host на основе полученной цели-запроса, а не пересылать полученное значение поля Host.

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

Сервер ДОЛЖЕН ответить кодом состояния 400 (неверный запрос) на любое сообщение запроса HTTP/1.1, в котором отсутствует поле заголовка Host, и на любое сообщение запроса, содержащее более одного поля заголовка Host, или поле заголовка Host с недопустимым значением поля.

5.5. URI действующего запроса

Поскольку цель запроса часто содержит только часть целевого URI пользовательского агента, сервер восстанавливает предполагаемую цель как «effective request URI» (эффективный URI запроса) для надлежащего обслуживания запроса. Эта реконструкция включает в себя как локальную конфигурацию сервера, так и информацию, передаваемую в запросе-цели, поле заголовка узла и контекст соединения.

Для пользовательского агента эффективным URI запроса является целевой URI.

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

Если конфигурация сервера (или исходящего шлюза) предоставляет фиксированную схему URI, эта схема используется для действующего URI запроса. В противном случае, если запрос получен через TCP-соединение, защищенное TLS, эффективной URI схемы запроса будет «https»; если нет, схема «http».

Если конфигурация сервера (или исходящего шлюза) предоставляет фиксированный компонент полномочий (authority) URI, эти полномочия используются для действующего URI запроса. Если нет, то, если цель запроса находится в форме полномочий, компонент полномочий действующего URI запроса такой же, как и у цели запроса. Если нет, то если поле заголовка «Host» снабжено непустым значением поля, компонент полномочий совпадает со значением поля «Host». В противном случае компоненту полномочий назначается имя по умолчанию, настроенное для сервера, и, если номер входящего TCP-порта соединения отличается от порта по умолчанию для схемы URI действующего запроса, то используется двоеточие («:») и номер входящего порта (в десятичная форма) добавляются к компоненту полномочий.

Если цель запроса находится в форме авторизации (authority-form) или в форме звездочки (asterisk-form), объединенный путь и компонент запроса эффективного URI запроса будут пустыми. В противном случае объединенный компонент пути и запроса совпадает с целевым объектом запроса.

Компоненты действующего URI запроса, однажды определенные как указано выше, могут быть объединены в форму абсолютного URI путем объединения схемы, «: //», полномочий и комбинированного компонента пути и запроса.

Пример 1: следующее сообщение получено по небезопасному TCP-соединению

GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.example.org:8080

имеет эффективный URI запроса

http://www.example.org:8080/pub/WWW/TheProject.html

Пример 2: следующее сообщение получено через TCP-соединение, защищенное TLS

OPTIONS * HTTP/1.1
Host: www.example.org

имеет эффективный URI запроса

https://www.example.org

Получателям запроса HTTP/1.0, в котором отсутствует поле заголовка узла, может потребоваться использование эвристики (например, проверка пути URI для чего-то уникального для конкретного узла), чтобы угадать эффективный компонент полномочий URI действующего запроса.

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

5.6. Связывание ответа на запрос

HTTP не включает в себя идентификатор запроса для связи данного сообщения запроса с его соответствующими одним или несколькими ответными сообщениями. Следовательно, он основан на том, что порядок получения ответа точно соответствует порядку, в котором запросы выполняются по одному и тому же соединению. Более одного ответного сообщения на запрос возникает только тогда, когда один или несколько информационных ответов (1xx, см. Раздел 6.2 [RFC7231 #]) предшествуют окончательному ответу на тот же запрос.

Клиент, имеющий более одного невыполненного запроса на соединение, ДОЛЖЕН вести список ожидающих запросов в отправленном заказе и ДОЛЖЕН связывать каждое полученное ответное сообщение по этому соединению с запросом с наивысшим порядком, который еще не получил окончательный (не-1xx) ответ.

5.7. Пересылка сообщений

Как описано в разделе 2.3, посредники могут выполнять различные роли при обработке HTTP-запросов и ответов. Некоторые посредники используются для улучшения производительности или доступности. Другие используются для контроля доступа или для фильтрации содержимого. Поскольку поток HTTP имеет характеристики, аналогичные архитектуре канала и фильтра, нет никаких внутренних ограничений в той степени, в которой посредник может улучшать (или создавать помехи) любое направление потока.

Посредник, не действующий в качестве туннеля, ДОЛЖЕН реализовать поле заголовка Connection, как указано в Разделе 6.1, и исключить из пересылаемых полей, которые предназначены только для входящего соединения.

Посредник НЕ ДОЛЖЕН пересылать сообщение самому себе, если оно не защищено от бесконечного цикла запроса. Как правило, посредник должен распознавать собственные имена серверов, включая любые псевдонимы, локальные варианты или буквальные IP-адреса, и отвечать на такие запросы напрямую.

5.7.1. Заголовок Via

Поле заголовка «Via» указывает на наличие промежуточных протоколов и получателей между пользовательским агентом и сервером (по запросам) или между исходным сервером и клиентом (по ответам), аналогично полю заголовка «Received» в электронной почте (раздел 3.6.7 из [RFC5322 #]). С помощью Via можно отслеживать пересылку сообщений, избегать циклов запросов и определять возможности протокола отправителей в цепочке запросов / ответов.

Via = 1#( received-protocol RWS received-by [ RWS comment ] )

received-protocol = [ protocol-name "/" ] protocol-version ; смотри Раздел 6.7
received-by = ( uri-host [ ":" port ] ) / pseudonym
pseudonym = token

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

Прокси-сервер ДОЛЖЕН отправлять соответствующее поле заголовка Via, как описано ниже, в каждом сообщении, которое он передает. Шлюз HTTP-HTTP ДОЛЖЕН отправлять соответствующее поле заголовка Via в каждом входящем сообщении запроса и МОЖЕТ отправлять поле заголовка Via в переадресованных ответных сообщениях.

Для каждого посредника принятый протокол указывает протокол и версию протокола, используемые вышестоящим отправителем сообщения. Следовательно, значение поля Via записывает объявленные возможности протокола цепочки запросов/ответов таким образом, чтобы они оставались видимыми для последующих получателей; это может быть полезно для определения того, какие обратно несовместимые функции можно было бы безопасно использовать в ответ или в рамках более позднего запроса, как описано в разделе 2.6. Для краткости имя протокола опускается, когда принятый протокол HTTP.

Полученная часть значения поля обычно является хостом и необязательным номером порта сервера-получателя или клиента, который впоследствии переадресовал сообщение. Однако, если реальный хост считается конфиденциальной информацией, отправитель МОЖЕТ заменить ее псевдонимом. Если порт не указан, получатель МОЖЕТ интерпретировать его как означающий, что он был получен на TCP-порту по умолчанию, если он есть, для принятого протокола.

Отправитель МОЖЕТ генерировать комментарии в поле заголовка Via для идентификации программного обеспечения каждого получателя, аналогично полям заголовка User-Agent и Server. Однако все комментарии в поле Via являются необязательными, и получатель МОЖЕТ удалить их до пересылки сообщения.

Например, сообщение с запросом может быть отправлено от пользовательского агента HTTP/1.0 внутреннему прокси-серверу с кодовым названием «fred», который использует HTTP/1.1 для пересылки запроса общедоступному прокси-серверу на «p.example.net», который завершает запрос, отправив его на исходный сервер по адресу «www.example.com». Запрос, полученный www.example.com, будет иметь следующее поле заголовка Via:

Via: 1.0 fred, 1.1 p.example.net

Посреднику, используемому в качестве портала через сетевой брандмауэр, НЕ СЛЕДУЕТ пересылать имена и порты хостов в пределах области брандмауэра, если это явно не разрешено для этого. Если этот параметр не включен, такой посредник ДОЛЖЕН заменить каждый принимаемый хост любого хоста за брандмауэром соответствующим псевдонимом для этого хоста.

Посредник МОЖЕТ объединить упорядоченную подпоследовательность записей поля заголовка Via в одну такую запись, если записи имеют идентичные значения принятого протокола. Например,

Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

может быть свернуто

Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

Отправителю НЕ СЛЕДУЕТ объединять несколько записей, если они не находятся под одним и тем же организационным контролем и хосты уже не заменены псевдонимами. Отправитель НЕ ДОЛЖЕН объединять записи, которые имеют разные значения принятого протокола.

5.7.2. Трансформации

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

Прокси-сервер HTTP-HTTP называется «transforming proxy» (прокси-преобразователем), если он предназначен или настроен для изменения сообщений семантически значимым способом (т. е. Модификаций, помимо тех, которые требуются при обычной обработке HTTP, которые изменяют сообщение таким образом, чтобы быть значительным для исходного отправителя или потенциально значимым для нижестоящих получателей). Например, прокси-сервер преобразования может выступать в качестве общего сервера аннотаций (модифицируя ответы для включения ссылок на локальную базу данных аннотаций), фильтра вредоносных программ, транскодера формата или фильтра конфиденциальности. Предполагается, что такие преобразования желательны для любого клиента (или организации клиента), который выбрал прокси.

Если прокси-сервер получает целевой объект запроса с именем хоста, которое не является полностью определенным доменным именем, он МОЖЕТ добавить свой собственный домен к имени хоста, которое он получил при пересылке запроса. Прокси НЕ ДОЛЖЕН изменять имя хоста, если цель запроса содержит полное доменное имя.

Прокси НЕ ДОЛЖЕН изменять части «абсолютного пути» и «запроса» полученной цели-запроса при пересылке его на следующий входящий сервер, за исключением случаев, указанных выше, для замены пустого пути на слэш «/» или звёздочку «*».

Прокси МОЖЕТ изменить тело сообщения посредством применения или удаления кода передачи (Раздел 4).

Прокси НЕ ДОЛЖЕН преобразовывать полезную нагрузку (раздел 3.3 [RFC7231 #]) сообщения, которое содержит директиву управления преобразованием кэша без преобразования (раздел 5.2 [RFC7234 #]).

Прокси МОЖЕТ преобразовать полезную нагрузку сообщения, которое не содержит директиву управления кэшированием без преобразования. Прокси, который преобразует полезную нагрузку, ДОЛЖЕН добавить поле заголовка Warning с кодом предупреждения 214 («Преобразование применено»), если его еще нет в сообщении (см. Раздел 5.5 [RFC7234 #]). Прокси-сервер, который преобразует полезную нагрузку ответа 200 (ОК), может дополнительно информировать получателей в нисходящем направлении о том, что преобразование применено путем изменения кода состояния ответа на 203 (Неавторизованная информация) (раздел 6.3.4 [RFC7231 #]).

Прокси-сервер НЕ ДОЛЖЕН изменять поля заголовка, которые предоставляют информацию о конечных точках цепочки связи, состоянии ресурса или выбранном представлении (кроме полезной нагрузки), если определение поля специально не допускает такую модификацию или модификация не считается необходимой для конфиденциальности или безопасности.

6. Управление подключением

Обмен сообщениями HTTP не зависит от базового протокола (ов) транспортного (transport-layer) или сеансового уровня (session-layer). HTTP предполагает только надежный транспорт с доставкой запросов по порядку и соответствующей доставкой ответов по порядку. Отображение структур HTTP-запросов и ответов на блоки данных базового транспортного протокола выходит за рамки данной спецификации.

Как описано в разделе 5.2, конкретные протоколы соединения, которые будут использоваться для взаимодействия HTTP, определяются конфигурацией клиента и целевым URI. Например, схема URI «http» (раздел 2.7.1) указывает на соединение по умолчанию TCP через IP с портом TCP по умолчанию, равным 80, но клиент может быть настроен на использование прокси-сервера через какое-либо другое соединение, порт или протокол.

Ожидается, что реализации HTTP будут участвовать в управлении соединениями, которое включает в себя поддержание состояния текущих соединений, установление нового соединения или повторное использование существующего соединения, обработку сообщений, полученных по соединению, обнаружение сбоев соединения и закрытие каждого соединения. Большинство клиентов поддерживают несколько соединений параллельно, в том числе более одного соединения на конечную точку сервера. Большинство серверов предназначены для поддержки тысяч одновременных соединений, в то же время контролируя очереди запросов, чтобы обеспечить добросовестное использование и обнаруживать атаки типа DOS «denial-of-service» (отказ в обслуживании).

6.1. Заголовок Connection

Поле заголовка «Connection» позволяет отправителю указать желаемые параметры управления для текущего соединения. Во избежание путаницы получателей в нисходящем направлении прокси или шлюз ДОЛЖНЫ удалить или заменить любые полученные параметры подключения перед пересылкой сообщения.

Когда поле заголовка помимо Connection используется для предоставления управляющей информации для текущего соединения или о текущем соединении, отправитель ДОЛЖЕН указать соответствующее имя поля в поле заголовка Connection. Прокси или шлюз ДОЛЖНЫ проанализировать полученное поле заголовка Connection перед пересылкой сообщения и для каждой опции соединения в этом поле удалить все поля заголовка из сообщения с тем же именем, что и у опции соединения, а затем удалить само поле заголовка Connection (или замените его собственными опциями соединения посредника для перенаправленного сообщения).

Следовательно, поле заголовка Connection обеспечивает декларативный способ отличить поля заголовка, которые предназначены только для непосредственного получателя («hop-by-hop» — «переход за прыжком»), от тех полей, которые предназначены для всех получателей в цепочке («end-to-end» — «сквозной конец»), позволяя сообщению быть само-описательным и позволяющим развертывать будущие расширения для конкретного соединения, не опасаясь, что они будут слепо перенаправлены более старыми посредниками.

Значение поля заголовка соединения имеет следующую грамматику:

Connection = 1#connection-option
connection-option = token

Параметры подключения не зависят от регистра.

Отправитель НЕ ДОЛЖЕН отправлять опцию соединения, соответствующую полю заголовка, которое предназначено для всех получателей полезной нагрузки. Например, Cache-Control никогда не подходит в качестве опции подключения (Раздел 5.2 [RFC7234 #]).

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

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

Параметр «close» (закрыть) для соединения определен для отправителя, чтобы сигнализировать, что это соединение будет закрыто после завершения ответа. Например,

Connection: close

в полях заголовка запроса или ответа указывается, что отправитель собирается закрыть соединение после завершения текущего запроса / ответа (раздел 6.6).

Клиент, который не поддерживает постоянные соединения, ДОЛЖЕН отправлять опцию «close» в каждом сообщении запроса.

Сервер, который не поддерживает постоянные соединения, ДОЛЖЕН отправлять опцию «close» в каждом ответном сообщении, которое не имеет кода состояния 1xx (информационный).

6.2. Установление

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

6.3. Упорство

HTTP/1.1 по умолчанию использует «persistent connections» (постоянные соединения), что позволяет передавать несколько запросов и ответов по одному соединению. Параметр соединения «close» используется, чтобы указать, что соединение не будет сохраняться после текущего запроса / ответа. Реализации HTTP ДОЛЖНЫ поддерживать постоянные соединения.

Получатель определяет, является ли соединение постоянным или нет, на основе версии протокола последнего принятого сообщения и поля заголовка соединения (если есть):

  • При наличии опции «close» соединение не будет сохраняться после текущего ответа; иначе,
  • Если получен протокол HTTP/1.1 (или более поздний), соединение будет сохраняться после текущего ответа; иначе,
  • Если получен протокол HTTP/1.0, присутствует опция соединения keep-alive, получатель не является прокси-сервером, а получатель желает соблюдать механизм HTTP-1.0 keep-alive, соединение будет сохраняться после текущий ответ; иначе,
  • Соединение закроется после текущего ответа.

Клиент МОЖЕТ отправлять дополнительные запросы на постоянное соединение до тех пор, пока он не отправит или не получит опцию «close», или не получит ответ HTTP/1.0 без опции соединения «keep-alive».

Чтобы оставаться постоянными, все сообщения в соединении должны иметь собственную длину сообщения (то есть одно сообщение, не определяемое закрытием соединения), как описано в разделе 3.3. Сервер ДОЛЖЕН прочитать все тело сообщения запроса или закрыть соединение после отправки своего ответа, поскольку в противном случае оставшиеся данные в постоянном соединении были бы неверно истолкованы как следующий запрос. Аналогично, клиент ДОЛЖЕН прочитать все тело ответного сообщения, если он намерен повторно использовать то же соединение для последующего запроса.

Прокси-сервер НЕ ДОЛЖЕН поддерживать постоянное соединение с клиентом HTTP/1.0 (см. Раздел 19.7.1 [RFC2068 #] для получения информации и обсуждения проблем с полем заголовка Keep-Alive, реализованного многими клиентами HTTP/1.0).

См. Приложение A.1.2 для получения дополнительной информации о обратной совместимости с клиентами HTTP/1.0.

6.3.1. Повторение запросов

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

Когда входящее соединение закрывается преждевременно, клиент МОЖЕТ открыть новое соединение и автоматически повторно передать прерванную последовательность запросов, если все эти запросы имеют идемпотентные методы (раздел 4.2.2 [RFC7231 #]). Прокси НЕ ДОЛЖЕН автоматически повторять неидемпотентные запросы.

Пользовательский агент НЕ ДОЛЖЕН автоматически повторять запрос неидемпотентным методом, если у него нет некоторых средств, чтобы знать, что семантика запроса фактически идемпотентна, независимо от метода, или каких-либо средств, чтобы обнаружить, что исходный запрос никогда не применялся. Например, пользовательский агент, который знает (посредством проектирования или конфигурации), что POST-запрос к данному ресурсу является безопасным, может автоматически повторить этот запрос. Аналогичным образом, пользовательский агент, специально разработанный для работы с хранилищем управления версиями, может быть в состоянии восстановиться после частичного сбоя, проверив целевую версию (и) ресурса после неудачного соединения, отменив или исправив любые изменения, которые были применены частично, а затем автоматически повторять запросы, которые не удалось.

Клиент НЕ ДОЛЖЕН автоматически повторять неудачную автоматическую повторную попытку.

6.3.2. Конвейеризация

Клиент, который поддерживает постоянные соединения, МОЖЕТ «конвейеризовать» свои запросы (то есть отправлять несколько запросов, не ожидая каждого ответа). Сервер МОЖЕТ обрабатывать последовательность конвейерных запросов параллельно, если все они имеют безопасные методы (Раздел 4.2.1 [RFC7231 #]), но он ДОЛЖЕН отправлять соответствующие ответы в том же порядке, в котором были получены запросы.

Клиенту, который передает запросы, СЛЕДУЕТ повторить неотвеченные запросы, если соединение закрывается до того, как получит все соответствующие ответы. При повторной попытке конвейерных запросов после неудачного соединения (соединение, явно не закрытое сервером в его последнем завершенном ответе), клиент НЕ ДОЛЖЕН выполнять конвейер сразу после установления соединения, поскольку первый оставшийся запрос в предыдущем конвейере мог вызвать ответ об ошибке, который может быть снова потерян, если несколько запросов отправляются на преждевременно закрытом соединении (см. проблему сброса TCP, описанную в разделе 6.6).

Идемпотентные методы (раздел 4.2.2 [RFC7231 #]) важны для конвейерной передачи, поскольку их можно автоматически повторить после сбоя соединения. Пользовательскому агенту НЕ СЛЕДУЕТ выполнять конвейерные запросы после неидемпотентного метода, пока не будет получен код состояния окончательного ответа для этого метода, если только у пользовательского агента нет средств для обнаружения и восстановления после частичного сбоя, включающего конвейерную последовательность.

Посредник, который получает конвейерные запросы, МОЖЕТ направлять эти запросы при пересылке их входящих, поскольку он может полагаться на исходящих пользовательских агентов, чтобы определить, какие запросы могут быть безопасно переданы по конвейеру. Если входящее соединение не удается до получения ответа, посредник конвейера МОЖЕТ попытаться повторить последовательность запросов, которые еще не получили ответ, если все запросы имеют идемпотентные методы; в противном случае посреднику конвейера СЛЕДУЕТ пересылать любые полученные ответы, а затем закрывать соответствующее исходящее соединение (я), чтобы исходящий пользовательский агент мог восстановиться соответствующим образом.

6.4. Совпадение

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

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

Множественные соединения обычно используются, чтобы избежать проблемы «head-of-line blocking» (блокирования заголовка), когда запрос, который требует значительной обработки на стороне сервера и/или имеет большую полезную нагрузку, блокирует последующие запросы в том же соединении. Однако каждое соединение потребляет ресурсы сервера. Кроме того, использование нескольких соединений может вызвать нежелательные побочные эффекты в перегруженных сетях.

Обратите внимание, что сервер может отклонить трафик, который он считает неправильным или характерным для атаки типа «denial-of-service» «отказ в обслуживании», такой как чрезмерное количество открытых соединений от одного клиента.

6.5. Сбои и таймауты

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

Клиенту или серверу, желающему установить тайм-аут, СЛЕДУЕТ изящно закрыть соединение. Реализации ДОЛЖНЫ постоянно отслеживать открытые соединения на предмет принятого сигнала закрытия и реагировать на него соответствующим образом, поскольку быстрое закрытие обеих сторон соединения позволяет восстанавливать выделенные системные ресурсы.

Клиент, сервер или прокси МОЖЕТ закрыть транспортное соединение в любое время. Например, клиент мог начать отправлять новый запрос в то же время, когда сервер решил закрыть «idle» (незанятое) соединение. С точки зрения сервера, соединение закрывается, пока оно не используется, но с точки зрения клиента, запрос находится в процессе.

Сервер ДОЛЖЕН поддерживать постоянные соединения, когда это возможно, и разрешать механизмам управления потоками базового транспорта разрешать временные перегрузки, а не прерывать соединения с ожиданием, что клиенты будут повторять попытки. Последний метод может усугубить перегрузку сети.

Клиент, отправляющий тело сообщения, ДОЛЖЕН контролировать сетевое соединение на предмет ответа об ошибке во время передачи запроса. Если клиент видит ответ, который указывает, что сервер не желает получать тело сообщения и закрывает соединение, клиент ДОЛЖЕН немедленно прекратить передачу тела и закрыть свою сторону соединения.

6.6. Срывание

Поле заголовка Connection (раздел 6.1) предоставляет опцию «close» соединение, которую отправитель ДОЛЖЕН отправить, когда он хочет закрыть соединение после текущей пары запрос/ответ.

Клиент, который отправляет опцию «close» соединение, НЕ ДОЛЖЕН отправлять дополнительные запросы по этому соединению (после того, которое содержит «close») и ДОЛЖЕН закрывать соединение после прочтения окончательного ответного сообщения, соответствующего этому запросу.

Сервер, который получает опцию «close», ДОЛЖЕН инициировать закрытие соединения (см. Ниже) после отправки окончательного ответа на запрос, содержащий «close». Сервер ДОЛЖЕН отправить опцию «close» в своем окончательном ответе на это соединение. Сервер НЕ ДОЛЖЕН обрабатывать любые дальнейшие запросы, полученные по этому соединению.

Сервер, который отправляет опцию «close», ДОЛЖЕН инициировать закрытие соединения (см. Ниже) после отправки ответа, содержащего «close». Сервер НЕ ДОЛЖЕН обрабатывать любые дальнейшие запросы, полученные по этому соединению.

Клиент, который получает опцию «close», ДОЛЖЕН прекратить отправку запросов по этому соединению и закрыть соединение после прочтения ответного сообщения, содержащего «close»; если по соединению были отправлены дополнительные конвейерные запросы, клиент НЕ ДОЛЖЕН предполагать, что они будут обработаны сервером.

Если сервер выполняет немедленное закрытие TCP-соединения, существует значительный риск того, что клиент не сможет прочитать последний HTTP-ответ. Если сервер получает дополнительные данные от клиента по полностью закрытому соединению, например, другой запрос, отправленный клиентом до получения ответа сервера, стек TCP сервера отправит клиенту пакет сброса; К сожалению, пакет сброса может стереть неподтвержденные входные буферы клиента, прежде чем они будут прочитаны и интерпретированы синтаксическим анализатором HTTP клиента.

Чтобы избежать проблемы сброса TCP, серверы обычно закрывают соединение поэтапно. Во-первых, сервер выполняет половину закрытия, закрывая только сторону записи соединения чтения/записи. Затем сервер продолжает считывать данные из соединения до тех пор, пока клиент не получит соответствующее закрытие или пока сервер не будет достаточно уверен, что его собственный стек TCP получил подтверждение от клиента пакета (пакетов), содержащего последний ответ сервера. Наконец, сервер полностью закрывает соединение.

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

6.7. Поле заголовка Upgrade

Поле заголовка «Upgrade» предназначено для обеспечения простого механизма перехода от HTTP/1.1 к другому протоколу в том же соединении. Клиент МОЖЕТ отправить список протоколов в поле заголовка Upgrade запроса, чтобы предложить серверу переключиться на один или несколько из этих протоколов в порядке убывания предпочтения перед отправкой окончательного ответа. Сервер МОЖЕТ игнорировать полученное поле заголовка Upgrade, если он хочет продолжать использовать текущий протокол для этого соединения. Обновление не может быть использовано, чтобы настаивать на изменении протокола.

Upgrade = 1#protocol


protocol = protocol-name ["/" protocol-version]
protocol-name = token
protocol-version = token

Сервер, который отправляет ответ 101 (Коммутационные протоколы), ДОЛЖЕН послать поле заголовка Upgrade, чтобы указать новый протокол (ы), на которые переключается соединение; если переключаются несколько уровней протоколов, отправитель ДОЛЖЕН перечислять протоколы в порядке возрастания уровней. Сервер НЕ ДОЛЖЕН переключаться на протокол, который не был указан клиентом в соответствующем поле заголовка обновления. Сервер МОЖЕТ выбрать игнорирование порядка предпочтений, указанного клиентом, и выбрать новый протокол (ы) на основе других факторов, таких как характер запроса или текущая нагрузка на сервер.

Сервер, который отправляет ответ 426 (требуется обновление), ДОЛЖЕН отправить поле заголовка Upgrade, чтобы указать приемлемые протоколы в порядке убывания предпочтения.

Сервер МОЖЕТ отправлять поле заголовка Upgrade в любом другом ответе, чтобы объявить, что он реализует поддержку обновления до перечисленных протоколов, в порядке убывания предпочтения, когда это уместно для будущего запроса.

Ниже приведен гипотетический пример, отправленный клиентом:

GET /hello.txt HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

Возможности и характер связи прикладного уровня после смены протокола полностью зависят от новых выбранных протоколов. Однако сразу после отправки ответа 101 (коммутационные протоколы) сервер, как ожидается, продолжит отвечать на исходный запрос, как если бы он получил свой эквивалент в новом протоколе (т. е. Сервер все еще имеет невыполненный запрос для удовлетворения после протокола был изменен и, как ожидается, будет делать это, не требуя повторения запроса).

Например, если поле заголовка Upgrade получено в запросе GET, и сервер решает переключить протоколы, он сначала отвечает сообщением 101 (Switching Protocols) в HTTP/1.1, а затем сразу следует за ним с новым протоколом, эквивалентным ответу к GET на целевой ресурс. Это позволяет обновить соединение до протоколов с той же семантикой, что и для HTTP, без затрат на задержку дополнительного обхода. Сервер НЕ ДОЛЖЕН переключать протоколы, если новый протокол не учитывает семантику принятых сообщений; запрос OPTIONS может быть выполнен любым протоколом.

Ниже приведен пример ответа на указанный гипотетический запрос:

HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: HTTP/2.0
[... поток данных переключается на HTTP / 2.0 с соответствующим ответом (как определено новым протоколом) на запрос «GET /hello.txt» ...]

Когда отправляется Upgrade, отправитель ДОЛЖЕН также отправить поле заголовка Connection (раздел 6.1), в котором содержится опция соединения «upgrade» (обновление), чтобы предотвратить случайную пересылку обновления посредниками, которые могут не реализовать перечисленные протоколы. Сервер ДОЛЖЕН игнорировать поле заголовка Upgrade, полученное в запросе HTTP/1.0.

Клиент не может начать использовать обновленный протокол в соединении, пока он полностью не отправит сообщение с запросом (то есть клиент не может изменить протокол, который он отправляет в середине сообщения). Если сервер получает оба поля заголовка Upgrade и Expect с ожиданием «100-continue» (раздел 5.1.1 [RFC7231 #]), сервер ДОЛЖЕН отправить ответ 100 (Continue) перед отправкой ответа 101 (Switching Protocols).

Поле заголовка Upgrade применяется только к протоколам коммутации поверх существующего соединения; его нельзя использовать для переключения протокола основного соединения (транспортного) или для переключения существующего соединения на другое соединение. Для этих целей более целесообразно использовать ответ 3xx (Перенаправление) (Раздел 6.4 [RFC7231 #]).

Эта спецификация определяет только имя протокола «HTTP» для использования семейством протоколов передачи гипертекста, как это определено правилами HTTP-версии в разделе 2.6 и будущими обновлениями этой спецификации. Дополнительные токены должны быть зарегистрированы в IANA с использованием процедуры регистрации, определенной в разделе 8.6.

7. Расширение списка ABNF: #rule

Расширение #rule к правилам ABNF [RFC5234 #] используется для улучшения читабельности в определениях некоторых значений полей заголовка.

Конструкция решётки «#» определена, аналогично звёздочке «*», для определения разделенных запятыми списков элементов. Полная форма — это «<n> # <m> элемент», указывающий не менее <n> и не более <m> элементов, каждый из которых разделен запятой («,») и необязательным пробелом (OWS).

В любом производстве, которое использует конструкцию списка, отправитель НЕ ДОЛЖЕН генерировать пустые элементы списка. Другими словами, отправитель ДОЛЖЕН генерировать списки, которые удовлетворяют следующему синтаксису:

1#element => element *( OWS "," OWS element )

и:

#element => [ 1#element ]

и для n> = 1 и m> 1:

<n>#<m>element => element <n-1>*<m-1>( OWS "," OWS element )

Для совместимости с устаревшими правилами списка получатель ДОЛЖЕН проанализировать и игнорировать разумное количество пустых элементов списка: достаточно для обработки распространенных ошибок отправителей, которые объединяют значения, но не настолько, чтобы их можно было использовать в качестве механизма отказа в обслуживании (denial-of-service). Другими словами, получатель ДОЛЖЕН принимать списки, которые удовлетворяют следующему синтаксису:

#element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )

Пустые элементы не влияют на количество присутствующих элементов.

Например, учитывая эти производства ABNF:

example-list = 1#example-list-elmt
example-list-elmt = token ; смотри Раздел 3.2.6

Тогда следующие допустимые значения для example-list (не включая двойные кавычки, которые присутствуют только для разграничения):

"foo,bar"
"foo ,bar,"
"foo , ,bar,charlie "

Напротив, следующие значения будут недопустимыми, так как для создания списка примеров требуется хотя бы один непустой элемент:

""
","
", ,"

Приложение B показывает собранный ABNF для получателей после того, как конструкции списка были расширены.

8. Соображения IANA

8.1. Регистрация поля заголовка

Поля заголовка HTTP зарегистрированы в реестре «Заголовки сообщений», который ведется по адресу: <http://www.iana.org/assignments/message-headers/>.

Этот документ определяет следующие поля заголовка HTTP, поэтому реестр «Имена полей заголовка постоянного сообщения» был соответствующим образом обновлен (см. [BCP90]).

Имя поля заголовка Протокол Статус Определено в  …
Connection http standard Раздел 6.1
Content-Length http standard Раздел 3.3.2
Host http standard Раздел 5.4
TE http standard Раздел 4.3
Trailer http standard Раздел 4.4
Transfer-Encoding http standard Раздел 3.3.1
Upgrade http standard Раздел 6.7
Via http standard Раздел 5.7.1

Таблица

Кроме того, имя поля заголовка «Close» было зарегистрировано как «reserved» (зарезервированное), поскольку использование этого имени в качестве поля заголовка HTTP может конфликтовать с опцией «close» соединения поля заголовка Connection (раздел 6.1).

Имя поля заголовка Протокол Статус Определено в  …
Close http reserved Раздел 8.1

Таблица

Контроллер изменений: «IETF (iesg@ietf.org) — Целевая рабочая группа по Интернету».

8.2. Регистрация схемы URI

IANA ведет реестр схем URI [BCP115] по адресу <http://www.iana.org/assignments/uri-schemes/>.

Этот документ определяет следующие схемы URI, поэтому реестр «Схемы постоянных URI» был соответствующим образом обновлен.

URI схема Описание Определено в  …
http Hypertext Transfer Protocol Раздел 2.7.1
https Hypertext Transfer Protocol Secure Раздел 2.7.2

Таблица

8.3. Регистрация интернет медиа типа

IANA ведет реестр типов интернет-медиа [BCP13] по адресу <http://www.iana.org/assignments/media-types>.

Этот документ служит спецификацией для типов мультимедиа в Интернете «message/http» и «application/http«. Следующее было зарегистрировано в IANA.

8.3.1. Интернет медиа тип «message/http»

Тип «message/http» можно использовать для включения одного HTTP-запроса или ответного сообщения, при условии, что оно подчиняется ограничениям MIME для всех типов «message» (сообщений), касающихся длины строки и кодировок.

Имя типа: message
Название подтипа: http
Обязательные параметры: N / A
Необязательные параметры: version, msgtype

версия (version): номер HTTP-версии вложенного сообщения (например, «1.1»). Если нет, версия может быть определена из первой строки тела.

тип сообщения (msgtype): тип сообщения — «request» (запрос) или «response» (ответ). Если нет, тип можно определить по первой строке тела.

Вопросы кодирования: разрешены только «7-битные» (7bit), «8-битные» (8bit) или «двоичные» (binary)

Вопросы безопасности: см. Раздел 9

Вопросы совместимости: нет данных

Опубликованная спецификация: эта спецификация (см. Раздел 8.3.1).

Приложения, использующие этот тип носителя: N / A

Особенности идентификатора фрагмента: N / A

Дополнительная информация:

Магическое число (а): N / A

Устаревшие псевдонимы для этого типа: N / A

Расширение файла (ов): N / A

Код (ы) типов файлов Macintosh: N / A

Контактное лицо и адрес электронной почты для получения дополнительной информации: см. Раздел «Адреса авторов».

Использование по назначению: COMMON

Ограничения на использование: N / A

Автор: см. Раздел «Адреса авторов».

Сменить контроллер: IESG

8.3.2. Интернет медиа тип «application/http»

Тип «application/http» может использоваться для включения в конвейер одного или нескольких HTTP-запросов или ответных сообщений (не смешанных).

Введите имя: application

Название подтипа: http

Обязательные параметры: N / A

Необязательные параметры: version, msgtype

version: номер версии HTTP вложенных сообщений (например, «1.1»). Если нет, версия может быть определена из первой строки тела.

msgtype: тип сообщения — «запрос» или «ответ». Если нет, тип можно определить по первой строке тела.

Вопросы кодирования: HTTP-сообщения, заключенные в этот тип, имеют «двоичный» формат; использование соответствующей Content-Transfer-Encoding требуется при передаче по электронной почте.

Вопросы безопасности: см. Раздел 9

Вопросы совместимости: нет данных

Опубликованная спецификация: эта спецификация (см. Раздел 8.3.2).

Приложения, использующие этот тип носителя: N / A

Особенности идентификатора фрагмента: N / A

Дополнительная информация:

Устаревшие псевдонимы для этого типа: N / A

Магическое число (а): N / A

Расширение файла (ов): N / A

Код (ы) типов файлов Macintosh: N / A

Контактное лицо и адрес электронной почты для получения дополнительной информации: см. Раздел «Адреса авторов».

Использование по назначению: COMMON

Ограничения на использование: N / A

Автор: см. Раздел «Адреса авторов».

Сменить контроллер: IESG

8.4. Реестр передачи кодирования

«Реестр кодирования передачи HTTP» определяет пространство имен для имен кодирования передачи. Он поддерживается по адресу <http://www.iana.org/assignments/http-parameters>.

8.4.1. Процедура

Регистрации ДОЛЖНЫ включать следующие поля:

  • Имя
  • Описание
  • Указатель на текст спецификации

Имена кодировок передачи НЕ ДОЛЖНЫ перекрываться с именами кодировок контента (раздел 3.1.2.1 [RFC7231 #]), если только преобразование кодирования не является идентичным, как в случае кодировок сжатия, определенных в разделе 4.2.

Значения, которые должны быть добавлены в это пространство имен, требуют проверки IETF (см. Раздел 4.1 [RFC5226 #]) и ДОЛЖНЫ соответствовать цели кодирования передачи, определенной в данной спецификации.

Использование имен программ для идентификации форматов кодирования нежелательно и не рекомендуется для будущих кодировок.

8.4.2. Постановка на учет

«Реестр кодов передачи HTTP» обновлен следующими регистрациями:

Имя кодировки передачи HTTP Описание Определено в  …
chunked Передача в серии фрагментов Раздел 4.1
compress UNIX «compress» формат данных [Welch] Раздел 4.2.1
deflate «deflate» сжатые данные ([RFC1951 #]) внутри формата данных «zlib» ([RFC1950 #]) Раздел 4.2.2
gzip Формат файла GZIP [RFC1952 #] Раздел 4.2.3
x-compress Устаревший (псевдоним для сжатия) Раздел 4.2.1
x-gzip Устаревший (псевдоним для gzip) Раздел 4.2.3

Таблица

8.5. Регистрация кодирования контента

IANA поддерживает «Реестр кодирования содержимого HTTP» по адресу <http://www.iana.org/assignments/http-parameters>.

«Реестр кодирования содержимого HTTP» обновлен следующими регистрациями:

Имя кодировки передачи HTTP Описание Определено в  …
compress UNIX «compress» формат данных [Welch] Раздел 4.2.1
deflate «deflate» сжатые данные ([RFC1951 #]) внутри формата данных «zlib» ([RFC1950 #]) Раздел 4.2.2
gzip Формат файла GZIP [RFC1952 #] Раздел 4.2.3
x-compress Устаревший (псевдоним для сжатия) Раздел 4.2.1
x-gzip Устаревший (псевдоним для gzip) Раздел 4.2.3

Таблица

8.6. Обновление реестра токенов

«Реестр маркеров обновления протокола передачи гипертекста (HTTP)» определяет пространство имен для токенов имени протокола, используемых для идентификации протоколов в поле заголовка обновления. Реестр поддерживается по адресу <http://www.iana.org/assignments/http-upgrade-tokens>.

8.6.1. Процедура

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

Регистрация происходит по принципу «первым пришел — первым обслужен» (см. Раздел 4.1 [RFC5226 #]) и подчиняется следующим правилам:

  1. Токен имени протокола после регистрации остается навсегда зарегистрированным.
  2. Регистрация ДОЛЖНА указать ответственную сторону за регистрацию.
  3. При регистрации ДОЛЖЕН называться контактный пункт.
  4. Регистрация МОЖЕТ назвать набор спецификаций, связанных с этим токеном. Такие спецификации не должны быть общедоступными.
  5. Регистрации СЛЕДУЕТ назвать набор ожидаемых токенов «версии протокола», связанных с этим токеном во время регистрации.
  6. Ответственная сторона МОЖЕТ изменить регистрацию в любое время. IANA будет вести учет всех таких изменений и предоставлять их по запросу.
  7. IESG МОЖЕТ перенести ответственность за токен протокола. Обычно это используется только в том случае, если с ответственной стороной невозможно связаться.

Эта процедура регистрации для HTTP-маркеров обновления заменяет ранее определенную в разделе 7.2 [RFC2817 #].

8.6.2. Обновление регистрации токенов

Запись «HTTP» в реестре токенов обновления была обновлена с помощью следующей регистрации:

Значение Описание Ожидаемые версии токенов Определено в  …
HTTP Hypertext Transfer Protocol любой DIGIT.DIGIT (например, «2.0») Раздел 2.6

Таблица

Ответственная сторона: «IETF (iesg@ietf.org) — рабочая группа по инженерным проблемам интернета».

9. Вопросы безопасности

Этот раздел предназначен для информирования разработчиков, поставщиков информации и пользователей об известных соображениях безопасности, касающихся синтаксиса, анализа и маршрутизации HTTP-сообщений. Соображения безопасности относительно семантики HTTP и полезных нагрузок рассматриваются в [RFC7231 #].

9.1. Учреждение власти (полномочий)

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

К сожалению, установление авторитета может быть затруднено. Например, фишинг представляет собой атаку на восприятие пользователем полномочий (authority), где это восприятие может быть введено в заблуждение путем представления аналогичного фирменного знака в гипертексте, возможно, с помощью userinfo, запутывающего компонент полномочий (см. Раздел 2.7.1). Пользовательские агенты могут уменьшить влияние фишинговых атак, позволяя пользователям легко проверять целевой URI перед выполнением действия, заметно выделяя (или отклоняя) информацию пользователя, когда она присутствует, и не отправляя сохраненные учетные данные и файлы cookie, когда ссылающийся документ взят из неизвестного или ненадежного источника.

Когда зарегистрированное имя используется в компоненте полномочий, схема URI «http» (раздел 2.7.1) опирается на локальную службу разрешения имен пользователя, чтобы определить, где он может найти достоверные ответы. Это означает, что любая атака на таблицу сетевых хостов пользователя, кэшированные имена или библиотеки разрешения имен становится средством для атаки на установление полномочий. Аналогичным образом, выбор пользователем сервера для службы доменных имен (DNS) и иерархия серверов, с которых он получает результаты разрешения, могут повлиять на подлинность сопоставления адресов; Расширения безопасности DNS (DNSSEC, [RFC4033 #]) являются одним из способов повышения подлинности.

Кроме того, после получения IP-адреса установление полномочий для «http» URI становится уязвимым для атак на маршрутизацию интернет-протокола.

Схема «https» (раздел 2.7.2) предназначена для предотвращения (или, по крайней мере, раскрытия) многих из этих потенциальных атак на установление полномочий при условии, что согласованное соединение TLS защищено, и клиент должным образом проверяет, соответствует ли идентификационный номер сервера связи компонент полномочий целевого URI (см. [RFC2818 #]). Правильно осуществить такую проверку может быть сложно (см. [Georgiev]).

9.2. Риски посредников

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

Посредники, которые содержат общий кэш, особенно уязвимы для атак отравления кешем, как описано в Разделе 8 [RFC7234 #].

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

Пользователи должны знать, что посредники не более заслуживают доверия, чем люди, которые ими управляют; Сам HTTP не может решить эту проблему.

9.3. Атаки через длину элемента протокола

Поскольку HTTP использует в основном текстовые поля, разделенные символами, синтаксические анализаторы часто уязвимы для атак, основанных на отправке очень длинных (или очень медленных) потоков данных, особенно там, где реализация ожидает элемент протокола без предопределенной длины.

Для обеспечения функциональной совместимости даются конкретные рекомендации для ограничения минимального размера строки запроса (раздел 3.1.1) и полей заголовка (раздел 3.2). Это минимальные рекомендации, выбранные для поддержки даже реализациями с ограниченными ресурсами; ожидается, что большинство реализаций выберут существенно более высокие ограничения.

Сервер может отклонить сообщение с слишком длинным целевым объектом запроса (раздел 6.5.12 [RFC7231 #]) или слишком большой полезной нагрузкой запроса (раздел 6.5.11 [RFC7231 #]). Дополнительные коды состояния, связанные с ограничениями пропускной способности, определены расширениями HTTP [RFC6585 #].

Получатели должны тщательно ограничивать степень, в которой они обрабатывают другие элементы протокола, включая (но не ограничиваясь) методы запроса, фразы состояния ответа, имена полей заголовков, числовые значения и фрагменты тела. Неспособность ограничить такую ​​обработку может привести к переполнению буфера, арифметическому переполнению или повышенной уязвимости к атакам типа «отказ в обслуживании».

9.4. Разделение ответов

Разделение ответов (a.k.a, внедрение CRLF) — это распространенная техника, используемая в различных атаках на использование Интернета, которая использует линейный характер формирования HTTP-сообщений и упорядоченную ассоциацию запросов к ответам на постоянные соединения [Klein]. Этот метод может быть особенно разрушительным, когда запросы проходят через общий кеш.

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

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

Обычной защитой от разделения ответов является фильтрация запросов данных, которые выглядят как закодированные CR и LF (например, «%0D» и «%0A»). Однако это предполагает, что сервер приложений выполняет только декодирование URI, а не более неясные преобразования данных, такие как транскодирование кодировок, преобразование сущностей XML, декодирование base64, переформатирование sprintf и т. д.. Более эффективное предотвращение заключается в предотвращении чего-либо, кроме библиотек протокола ядра сервера. от отправки CR или LF в разделе заголовка, что означает ограничение вывода полей заголовка API-интерфейсами, которые фильтруют плохие октеты и не позволяют серверам приложений выполнять запись непосредственно в поток протокола.

9.5. Запрос контрабанды

Контрабанда запросов ([Linhart]) — это метод, который использует различия в разборе протокола между различными получателями, чтобы скрыть дополнительные запросы (которые в противном случае могут быть заблокированы или отключены политикой) в явно безвредном запросе. Подобно разделению ответов, контрабанда запросов может привести к различным атакам на использование HTTP.

Эта спецификация ввела новые требования при разборе запросов, особенно в отношении формирования сообщений в разделе 3.3.3, для снижения эффективности контрабанды запросов.

9.6. Целостность сообщения

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

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

9.7. Конфиденциальность сообщения

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

Схема «https» может использоваться для идентификации ресурсов, которые требуют конфиденциального соединения, как описано в разделе 2.7.2.

9.8. Конфиденциальность информации журнала сервера

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

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

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

10. Благодарности

Это издание HTTP/1.1 основано на многих материалах, которые были внесены в RFC 1945 #, RFC 2068 #, RFC 2145 # и RFC 2616 #, включая существенный вклад предыдущих авторов, редакторов и председателей рабочих групп: Тима Бернерса-Ли, Ари Луотонена Рой Т. Филдинг, Хенрик Фристик Нильсен, Джим Геттис, Джеффри С. Могул, Ларри Масинтер и Пол Дж. Лич. Марк Ноттингем курировал эти усилия в качестве Председателя Рабочей группы.

С 1999 года следующие участники помогли улучшить HTTP-спецификацию, сообщая об ошибках, задавая умные вопросы, составляя или просматривая текст, а также оценивая открытые проблемы:

Adam Barth, Adam Roach, Addison Phillips, Adrian Chadd, Adrian Cole, Adrien W. de Croy, Alan Ford, Alan Ruttenberg, Albert Lunde, Alek Storm, Alex Rousskov, Alexandre Morgaut, Alexey Melnikov, Alisha Smith, Amichai Rothman, Amit Klein, Amos Jeffries, Andreas Maier, Andreas Petersson, Andrei Popov, Anil Sharma, Anne van Kesteren, Anthony Bryan, Asbjorn Ulsberg, Ashok Kumar, Balachander Krishnamurthy, Barry Leiba, Ben Laurie, Benjamin Carlyle, Benjamin Niven-Jenkins, Benoit Claise, Bil Corry, Bill Burke, Bjoern Hoehrmann, Bob Scheifler, Boris Zbarsky, Brett Slatkin, Brian Kell, Brian McBarron, Brian Pane, Brian Raymor, Brian Smith, Bruce Perens, Bryce Nesbitt, Cameron Heavon-Jones, Carl Kugler, Carsten Bormann, Charles Fry, Chris Burdess, Chris Newman, Christian Huitema, Cyrus Daboo, Dale Robert Anderson, Dan Wing, Dan Winship, Daniel Stenberg, Darrel Miller, Dave Cridland, Dave Crocker, Dave Kristol, Dave Thaler, David Booth, David Singer, David W. Morris, Diwakar Shetty, Dmitry Kurochkin, Drummond Reed, Duane Wessels, Edward Lee, Eitan Adler, Eliot Lear, Emile Stephan, Eran Hammer-Lahav, Eric D. Williams, Eric J. Bowman, Eric Lawrence, Eric Rescorla, Erik Aronesty, EungJun Yi, Evan Prodromou, Felix Geisendoerfer, Florian Weimer, Frank Ellermann, Fred Akalin, Fred Bohle, Frederic Kayser, Gabor Molnar, Gabriel Montenegro, Geoffrey Sneddon, Gervase Markham, Gili Tzabari, Grahame Grieve, Greg Slepak, Greg Wilkins, Grzegorz Calkowski, Harald Tveit Alvestrand, Harry Halpin, Helge Hess, Henrik Nordstrom, Henry S. Thompson, Henry Story, Herbert van de Sompel, Herve Ruellan, Howard Melman, Hugo Haas, Ian Fette, Ian Hickson, Ido Safruti, Ilari Liusvaara, Ilya Grigorik, Ingo Struck, J. Ross Nicoll, James Cloos, James H. Manger, James Lacey, James M. Snell, Jamie Lokier, Jan Algermissen, Jari Arkko,

Jeff Hodges (who came up with the term ’effective Request-URI’),

Jeff Pinner, Jeff Walden, Jim Luther, Jitu Padhye, Joe D. Williams, Joe Gregorio, Joe Orton, Joel Jaeggli, John C. Klensin, John C. Mallery, John Cowan, John Kemp, John Panzer, John Schneider, John Stracke, John Sullivan, Jonas Sicking, Jonathan A. Rees, Jonathan Billington, Jonathan Moore, Jonathan Silvera, Jordi Ros, Joris Dobbelsteen, Josh Cohen, Julien Pierre, Jungshik Shin, Justin Chapweske, Justin Erenkrantz, Justin James, Kalvinder Singh, Karl Dubost, Kathleen Moriarty, Keith Hoffman, Keith Moore, Ken Murchison, Koen Holtman, Konstantin Voronkov, Kris Zyp, Leif Hedstrom, Lionel Morand, Lisa Dusseault, Maciej Stachowiak, Manu Sporny, Marc Schneider, Marc Slemko, Mark Baker, Mark Pauley, Mark Watson, Markus Isomaki, Markus Lanthaler, Martin J. Duerst, Martin Musatov, Martin Nilsson, Martin Thomson, Matt Lynch, Matthew Cox, Matthew Kerwin, Max Clark, Menachem Dodge, Meral Shirazipour, Michael Burrows, Michael Hausenblas, Michael Scharf, Michael Sweet, Michael Tuexen, Michael Welzl, Mike Amundsen, Mike Belshe, Mike Bishop, Mike Kelly, Mike Schinkel, Miles Sabin, Murray S. Kucherawy, Mykyta Yevstifeyev, Nathan Rixham, Nicholas Shanks, Nico Williams, Nicolas Alvarez, Nicolas Mailhot, Noah Slater, Osama Mazahir, Pablo Castro, Pat Hayes, Patrick R. McManus, Paul E. Jones, Paul Hoffman, Paul Marquess, Pete Resnick, Peter Lepeska, Peter Occil, Peter Saint-Andre, Peter Watkins, Phil Archer, Phil Hunt, Philippe Mougin, Phillip Hallam-Baker, Piotr Dobrogost, Poul-Henning Kamp, Preethi Natarajan, Rajeev Bector, Ray Polk, Reto Bachmann-Gmuer, Richard Barnes, Richard Cyganiak, Rob Trace, Robby Simpson, Robert Brewer, Robert Collins, Robert Mattson, Robert O’Callahan, Robert Olofsson, Robert Sayre, Robert Siemer, Robert de Wilde, Roberto Javier Godoy, Roberto Peon, Roland Zink, Ronny Widjaja, Ryan Hamilton, S. Mike Dierken, Salvatore Loreto, Sam Johnston, Sam Pullara, Sam Ruby, Saurabh Kulkarni,

Scott Lawrence (who maintained the original issues list),

Sean B. Palmer, Sean Turner, Sebastien Barnoud, Shane McCarron, Shigeki Ohtsu, Simon Yarde, Stefan Eissing, Stefan Tilkov, Stefanos Harhalakis, Stephane Bortzmeyer, Stephen Farrell, Stephen Kent, Stephen Ludin, Stuart Williams, Subbu Allamaraju, Subramanian Moonesamy, Susan Hares, Sylvain Hellegouarch, Tapan Divekar, Tatsuhiro Tsujikawa, Tatsuya Hayashi, Ted Hardie, Ted Lemon, Thomas Broyer, Thomas Fossati, Thomas Maslen, Thomas Nadeau, Thomas Nordin, Thomas Roessler, Tim Bray, Tim Morgan, Tim Olsen, Tom Zhou, Travis Snoozy, Tyler Close, Vincent Murphy, Wenbo Zhu, Werner Baumann, Wilbur Streett, Wilfredo Sanchez Vega, William A. Rowe Jr., William Chan, Willy Tarreau, Xiaoshu Wang, Yaron Goland, Yngve Nysaeter Pettersen, Yoav Nir, Yogesh Bang, Yuchung Cheng, Yutaka Oiwa, Yves Lafon (long-time member of the editor team), Zed A. Shaw, and Zhong Yu.

См. Раздел 16 [RFC2616 #] для дополнительных благодарностей из предыдущих версий.

11. Ссылки

11.1. Нормативные ссылки

[RFC0793] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, September 1981.

[RFC1950] Deutsch, L. and J-L. Gailly, «ZLIB Compressed Data Format Specification version 3.3», RFC 1950, May 1996.

[RFC1951] Deutsch, P., «DEFLATE Compressed Data Format Specification version 1.3», RFC 1951, May 1996.

[RFC1952] Deutsch, P., Gailly, J-L., Adler, M., Deutsch, L., and G. Randers-Pehrson, «GZIP file format specification version 4.3», RFC 1952, May 1996.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, March 1997.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, January 2005.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, January 2008.

[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content», RFC 7231, June 2014.

[RFC7232] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests», RFC 7232, June 2014.

[RFC7233] Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Range Requests», RFC 7233, June 2014.

[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Caching», RFC 7234, June 2014.

[RFC7235] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Authentication», RFC 7235, June 2014.

[USASCII] American National Standards Institute, «Coded Character Set — 7-bit American Standard Code for Information Interchange», ANSI X3.4, 1986.

[Welch] Welch, T., «A Technique for High-Performance Data Compression», IEEE Computer 17(6), June 1984.

11.2. Информационные ссылки

[BCP115] Hansen, T., Hardie, T., and L. Masinter, «Guidelines and Registration Procedures for New URI Schemes», BCP 115, RFC 4395, February 2006.

[BCP13] Freed, N., Klensin, J., and T. Hansen, «Media Type Specifications and Registration Procedures», BCP 13, RFC 6838, January 2013.

[BCP90] Klyne, G., Nottingham, M., and J. Mogul, «Registration Procedures for Message Header Fields», BCP 90, RFC 3864, September 2004.

[Georgiev] Georgiev, M., Iyengar, S., Jana, S., Anubhai, R., Boneh, D., and V. Shmatikov, «The Most Dangerous Code in the World: Validating SSL Certificates in Nonbrowser Software», In Proceedings of the 2012 ACM Conference on Computer and Communications Security (CCS ’12), pp. 38-49, October 2012, <http://doi.acm.org/10.1145/2382196.2382204>.

[ISO-8859-1] International Organization for Standardization, «Information technology — 8-bit single-byte coded graphic character sets — Part 1: Latin alphabet No.
1», ISO/IEC 8859-1:1998, 1998.

[Klein] Klein, A., «Divide and Conquer — HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics», March 2004, <http://packetstormsecurity.com/papers/general/whitepaper_httpresponse.pdf>.

[Kri2001] Kristol, D., «HTTP Cookies: Standards, Privacy, and Politics», ACM Transactions on Internet Technology 1(2), November 2001, <http://arxiv.org/abs/cs.SE/0105018>.

[Linhart] Linhart, C., Klein, A., Heled, R., and S. Orrin, «HTTP Request Smuggling», June 2005, <http://www.watchfire.com/news/whitepapers.aspx>.

[RFC1919] Chatel, M., «Classical versus Transparent IP Proxies», RFC 1919, March 1996.

[RFC1945] Berners-Lee, T., Fielding, R., and H. Nielsen, «Hypertext Transfer Protocol — HTTP/1.0», RFC 1945, May 1996.

[RFC2045] Freed, N. and N. Borenstein, «Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies», RFC 2045, November 1996.

[RFC2047] Moore, K., «MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text», RFC 2047, November 1996.

[RFC2068] Fielding, R., Gettys, J., Mogul, J., Nielsen, H., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2068, January 1997.

[RFC2145] Mogul, J., Fielding, R., Gettys, J., and H. Nielsen, «Use and Interpretation of HTTP Version Numbers», RFC 2145, May 1997.

[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, «Hypertext Transfer Protocol — HTTP/1.1», RFC 2616, June 1999.

[RFC2817] Khare, R. and S. Lawrence, «Upgrading to TLS Within HTTP/1.1», RFC 2817, May 2000.

[RFC2818] Rescorla, E., «HTTP Over TLS», RFC 2818, May 2000.

[RFC3040] Cooper, I., Melve, I., and G. Tomlinson, «Internet Web Replication and Caching Taxonomy», RFC 3040, January 2001.

[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, «DNS Security Introduction and Requirements», RFC 4033, March 2005.

[RFC4559] Jaganathan, K., Zhu, L., and J. Brezak, «SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows», RFC 4559, June 2006.

[RFC5226] Narten, T. and H. Alvestrand, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 5226, May 2008.

[RFC5246] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, August 2008.

[RFC5322] Resnick, P., «Internet Message Format», RFC 5322, October 2008.

[RFC6265] Barth, A., «HTTP State Management Mechanism», RFC 6265, April 2011.

[RFC6585] Nottingham, M. and R. Fielding, «Additional HTTP Status Codes», RFC 6585, April 2012.

Приложение А. История версий HTTP

HTTP используется с 1990 года. Первая версия, позже названная HTTP/0.9, представляла собой простой протокол для передачи гипертекстовых данных через Интернет с использованием только одного метода запроса (GET) и без метаданных. HTTP/1.0, как определено в [RFC1945 #], добавил ряд методов запроса и MIME-подобного обмена сообщениями, позволяя передавать метаданные и размещать модификаторы в семантике запрос/ответ. Однако HTTP/1.0 недостаточно учитывал эффекты иерархических прокси, кэширования, необходимости постоянных соединений или виртуальных хостов на основе имен. Распространение не полностью реализованных приложений, называющих себя «HTTP/1.0», также потребовало изменения версии протокола, чтобы два взаимодействующих приложения могли определить истинные возможности друг друга.

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

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

Поскольку HTTP/0.9 не поддерживает поля заголовка в запросе, для него нет механизма поддержки виртуальных хостов на основе имен (выбор ресурса путем проверки поля заголовка Host). Любой сервер, который реализует виртуальные хосты на основе имен, должен отключить поддержку HTTP/0.9. Большинство запросов, которые выглядят как HTTP/0.9, на самом деле являются плохо сконструированными запросами HTTP/1.x, вызванными тем, что клиенту не удалось должным образом кодировать объект-запрос.

A.1. Отличия от HTTP/1.0

В этом разделе приведены основные различия между версиями HTTP/1.0 и HTTP/1.1.

A.1.1. Многосетевые веб-серверы

Требования о том, что клиенты и серверы поддерживают поле заголовка хоста (раздел 5.4), сообщают об ошибке, если она отсутствует в запросе HTTP/1.1, и принимают абсолютные URI (раздел 5.3), являются одними из наиболее важных изменений, определенных HTTP/1.1.

Старые клиенты HTTP/1.0 предполагали взаимно-однозначное соотношение IP-адресов и серверов; не было никакого другого установленного механизма для различения предполагаемого сервера запроса, кроме IP-адреса, на который был направлен этот запрос. Поле заголовка Host было введено во время разработки HTTP/1.1 и, хотя оно было быстро реализовано большинством браузеров HTTP/1.0, для всех запросов HTTP/1.1 были установлены дополнительные требования, чтобы обеспечить полное принятие. На момент написания этой статьи большинство HTTP-сервисов зависели от поля заголовка Host для таргетинга запросов.

A.1.2. Соединения Keep-Alive

В HTTP/1.0 каждое соединение устанавливается клиентом до запроса и закрывается сервером после отправки ответа. Однако в некоторых реализациях реализована явно согласованная («поддерживающая жизнь») версия постоянных соединений, описанная в разделе 19.7.1 [RFC2068 #].

Некоторые клиенты и серверы могут захотеть быть совместимыми с этими предыдущими подходами к постоянным соединениям, явно договариваясь о них с полем заголовка запроса «Connection: keep-alive». Однако некоторые экспериментальные реализации постоянных соединений HTTP/1.0 являются ошибочными; например, если прокси-сервер HTTP/1.0 не понимает Connection, он ошибочно перенаправит это поле заголовка на следующий входящий сервер, что приведет к зависанию соединения.

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

В результате клиентам рекомендуется не отправлять поле заголовка Proxy-Connection ни в каких запросах.

Клиентам также рекомендуется рассмотреть возможность использования Connection: внимательно следить за запросами; хотя они могут разрешать постоянные соединения с серверами HTTP/1.0, клиенты, использующие их, должны будут отслеживать соединение на предмет «hung» (зависших) запросов (которые указывают, что клиент должен прекратить отправку поля заголовка), и этот механизм не должен использоваться клиентами на все, когда используется прокси.

A.1.3. Введение Transfer-Encoding

HTTP/1.1 вводит поле заголовка Transfer-Encoding (раздел 3.3.1). Кодировки передачи должны быть декодированы до пересылки HTTP-сообщения по протоколу, совместимому с MIME.

А.2. Отличия от RFC 2616

Подход HTTP к обработке ошибок был объяснен. (Раздел 2.5)

HTTP-версия ABNF была уточнена, чтобы быть чувствительной к регистру. Кроме того, номера версий ограничены однозначными числами, поскольку известно, что реализации неправильно обрабатывают многозначные номера версий. (Раздел 2.6)

Userinfo (т.е. имя пользователя и пароль) теперь запрещены в HTTP и HTTPS URI из-за проблем безопасности, связанных с их передачей по проводам. (Раздел 2.7.1)

Схема HTTPS URI теперь определяется этой спецификацией; ранее это было сделано в Разделе 2.4 [RFC2818 #]. Кроме того, это подразумевает сквозную безопасность. (Раздел 2.7.2)

HTTP-сообщения могут быть (и часто) буферизуются реализациями; Несмотря на то, что иногда он доступен в виде потока, HTTP является протоколом, ориентированным на сообщения. Для улучшения совместимости были предложены минимальные поддерживаемые размеры для различных элементов протокола. (Раздел 3)

Неверный пробел вокруг имен полей теперь необходимо отклонить, поскольку его принятие представляет собой уязвимость системы безопасности. Продукция ABNF, определяющая поля заголовка, теперь перечисляет только значение поля. (Раздел 3.2)

Правила о неявной линейной пробеле между некоторыми грамматическими произведениями были удалены; теперь пробелы разрешены только там, где это определено в ABNF. (Раздел 3.2.3)

Поля заголовка, которые занимают несколько строк ((«line folding» (сворачивание строк)), являются устаревшими. (Раздел 3.2.4)

Октет NUL больше не разрешен в комментариях и тексте в кавычках, а обработка обратной косой черты в них была разъяснена. Правило цитируемой пары больше не позволяет экранировать управляющие символы, кроме HTAB. Содержимое не-US-ASCII в полях заголовка и фраза причины устарели и стали непрозрачными (правило TEXT было удалено). (Раздел 3.2.6)

Поля заголовка Bogus Content-Length теперь должны обрабатываться получателями как ошибки. (Раздел 3.3.2)

Алгоритм для определения длины тела сообщения был разъяснен, чтобы указать все особые случаи (например, управляемые методами или кодами состояния), которые влияют на него, и что новые элементы протокола не могут определять такие особые случаи. CONNECT — это новый, особый случай при определении длины тела сообщения. «multipart/byteranges» больше не является способом определения длины тела сообщения. (Раздел 3.3.3)

Токен кодирования передачи идентификатора был удален. (раздел 3.3 и раздел 4)

Длина куска (чанка, фрагмента) не включает количество октетов в заголовке куска и трейлере. Линии сгиба в расширениях куска запрещены. (Раздел 4.1)

Значение «deflate» («дефлятированного») кодирования контента было разъяснено. (Раздел 4.2.2)

Компоненты сегмент + запрос в RFC 3986 были использованы для определения цели запроса, а не abs_path из RFC 1808 #. Форма звездочки (asterisk-form) цели-запроса допускается только при использовании метода OPTIONS. (Раздел 5.3)

Введен термин «Effective Request URI» «Эффективный URI-запрос». (Раздел 5.5)

Шлюзам больше не нужно генерировать поля заголовка Via. (Раздел 5.7.1)

Точно, когда «close» варианты соединения должны быть отправлены, было выяснено. Кроме того, поля заголовка «hop-by-hop» (прыжок за прыжком) должны появляться в поле заголовка соединения; только то, что они определены как «hop-by-hop» в этой спецификации, не освобождает их. (Раздел 6.1)

Предел двух соединений на сервер был удален. Идемпотентная последовательность запросов больше не требуется повторять. Требование повторять запросы при определенных обстоятельствах, когда сервер преждевременно закрывает соединение, было удалено. Также были удалены некоторые посторонние требования, касающиеся того, когда серверам разрешается преждевременно закрывать соединения. (Раздел 6.3)

Семантика поля заголовка обновления теперь определяется в ответах, отличных от 101 (это было включено из [RFC2817 #]). Кроме того, порядок в значении поля теперь является значительным. (Раздел 6.7)

Пустые элементы списка в списках (например, поле заголовка списка, содержащее «,») устарели. (Раздел 7)

Регистрация кодировок передачи теперь требует проверки IETF (раздел 8.4)

Эта спецификация теперь определяет реестр токенов обновления, ранее определенный в разделе 7.2 [RFC2817 #]. (Раздел 8.6)

Ожидание поддержки запросов HTTP/0.9 было удалено. (Приложение A)

Проблемы с полями заголовка Keep-Alive и Proxy-Connection в запросах отмечены, с использованием последнего вообще не рекомендуется. (Приложение А.1.2)

Приложение B. Собранный ABNF

BWS = OWS

Connection = *( «,» OWS ) connection-option *( OWS «,» [ OWS connection-option ] )

Content-Length = 1*DIGIT

HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body]

HTTP-name = %x48.54.54.50 ; HTTP
HTTP-version = HTTP-name «/» DIGIT «.» DIGIT
Host = uri-host [ «:» port ]

OWS = *( SP / HTAB )

RWS = 1*( SP / HTAB )

TE = [ ( «,» / t-codings ) *( OWS «,» [ OWS t-codings ] ) ]
Trailer = *( «,» OWS ) field-name *( OWS «,» [ OWS field-name ] )
Transfer-Encoding = *( «,» OWS ) transfer-coding *( OWS «,» [ OWS transfer-coding ] )

URI-reference = <URI-reference, смотри [RFC3986 #], Раздел 4.1>
Upgrade = *( «,» OWS ) protocol *( OWS «,» [ OWS protocol ] )

Via = *( «,» OWS ) ( received-protocol RWS received-by [ RWS comment ] ) *( OWS «,» [ OWS ( received-protocol RWS received-by [ RWS comment ] ) ] )

absolute-URI = <absolute-URI, смотри [RFC3986 #], Раздел 4.3>
absolute-form = absolute-URI
absolute-path = 1*( «/» segment )
asterisk-form = «*»
authority = <authority, смотри [RFC3986 #], Раздел 3.2>
authority-form = authority

chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
chunk-data = 1*OCTET
chunk-ext = *( «;» chunk-ext-name [ «=» chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token / quoted-string
chunk-size = 1*HEXDIG
chunked-body = *chunk last-chunk trailer-part CRLF
comment = «(» *( ctext / quoted-pair / comment ) «)»
connection-option = token
ctext = HTAB / SP / %x21-27 ; ’!’-’’’
/ %x2A-5B ; ’*’-’[’
/ %x5D-7E ; ’]’-’~’
/ obs-text

field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-name = token
field-value = *( field-content / obs-fold )
field-vchar = VCHAR / obs-text
fragment = <fragment, смотри [RFC3986 #], Раздел 3.5>

header-field = field-name «:» OWS field-value OWS
http-URI = «http://» authority path-abempty [ «?» query ] [ «#» fragment ]
https-URI = «https://» authority path-abempty [ «?» query ] [ «#» fragment ]

last-chunk = 1*»0″ [ chunk-ext ] CRLF

message-body = *OCTET
method = token

obs-fold = CRLF 1*( SP / HTAB )
obs-text = %x80-FF
origin-form = absolute-path [ «?» query ]

partial-URI = relative-part [ «?» query ]
path-abempty = <path-abempty, смотри [RFC3986 #], Раздел 3.3>
port = <port, смотри [RFC3986 #], Раздел 3.2.3>
protocol = protocol-name [ «/» protocol-version ]
protocol-name = token
protocol-version = token
pseudonym = token

qdtext = HTAB / SP / «!» / %x23-5B ; ’#’-’[’ / %x5D-7E ; ’]’-’~’ / obs-text
query = <query, смотри [RFC3986 #], Раздел 3.4>
quoted-pair = «\» ( HTAB / SP / VCHAR / obs-text )
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE

rank = ( «0» [ «.» *3DIGIT ] ) / ( «1» [ «.» *3″0″ ] )
reason-phrase = *( HTAB / SP / VCHAR / obs-text )
received-by = ( uri-host [ «:» port ] ) / pseudonym
received-protocol = [ protocol-name «/» ] protocol-version
relative-part = <relative-part, смотри [RFC3986 #], Раздел 4.2>
request-line = method SP request-target SP HTTP-version CRLF
request-target = origin-form / absolute-form / authority-form / asterisk-form

scheme = <scheme, смотри [RFC3986 #], Раздел 3.1>
segment = <segment, смотри [RFC3986 #], Раздел 3.3>
start-line = request-line / status-line
status-code = 3DIGIT
status-line = HTTP-version SP status-code SP reason-phrase CRLF

t-codings = «trailers» / ( transfer-coding [ t-ranking ] )
t-ranking = OWS «;» OWS «q=» rank
tchar = «!» / «#» / «$» / «%» / «&» / «’» / «*» / «+» / «-» / «.» / «^» / «_» / «‘» / «|» / «~» / DIGIT / ALPHA
token = 1*tchar
trailer-part = *( header-field CRLF )
transfer-coding = «chunked» / «compress» / «deflate» / «gzip» / transfer-extension
transfer-extension = token *( OWS «;» OWS transfer-parameter )
transfer-parameter = token BWS «=» BWS ( token / quoted-string )

uri-host = <host, смотри [RFC3986 #], Раздел 3.2.2>

Индекс

A

absolute-form (of request-target) 42
accelerator 10
application/http Media Type 63
asterisk-form (of request-target) 43
authoritative response 67
authority-form (of request-target) 42-43

B

browser 7

C

cache 11
cacheable 12
captive portal 11
chunked (Coding Format) 28, 32, 36
client 7
close 51, 56
compress (Coding Format) 38
connection 7
Connection header field 51, 56
Content-Length header field 30

D

deflate (Coding Format) 38
Delimiters 27
downstream 10

E

effective request URI 45

G

gateway 10
Grammar

absolute-form 42
absolute-path 16
absolute-URI 16
ALPHA 6
asterisk-form 41, 43
authority 16
authority-form 42-43
BWS 25
chunk 36
chunk-data 36
chunk-ext 36
chunk-ext-name 36
chunk-ext-val 36
chunk-size 36
chunked-body 36
comment 27
Connection 51
connection-option 51
Content-Length 30
CR 6
CRLF 6
ctext 27
CTL 6
DIGIT 6
DQUOTE 6
field-content 23
field-name 23, 40
field-value 23
field-vchar 23
fragment 16
header-field 23, 37
HEXDIG 6
Host 44
HTAB 6
HTTP-message 19
HTTP-name 14
http-URI 17
HTTP-version 14
https-URI 18
last-chunk 36
LF 6
message-body 28
method 21
obs-fold 23
obs-text 27
OCTET 6
origin-form 42
OWS 25
partial-URI 16
port 16
protocol-name 47
protocol-version 47
pseudonym 47
qdtext 27
query 16
quoted-pair 27
quoted-string 27
rank 39
reason-phrase 22
received-by 47
received-protocol 47
request-line 21
request-target 41
RWS 25
scheme 16
segment 16
SP 6
start-line 21
status-code 22
status-line 22
t-codings 39
t-ranking 39
tchar 27
TE 39
token 27
Trailer 40
trailer-part 37
transfer-coding 35
Transfer-Encoding 28
transfer-extension 35
transfer-parameter 35
Upgrade 57
uri-host 16
URI-reference 16
VCHAR 6
Via 47

gzip (Coding Format) 39

H

header field 19
header section 19
headers 19
Host header field 44
http URI scheme 17
https URI scheme 17

I

inbound 9
interception proxy 11
intermediary 9

M

Media Type
application/http 63
message/http 62
message 7
message/http Media Type 62
method 21

N

non-transforming proxy 49

O

origin server 7
origin-form (of request-target) 42
outbound 10

P

phishing 67
proxy 10

R

recipient 7
request 7
request-target 21
resource 16
response 7
reverse proxy 10

S

sender 7
server 7
spider 7

T

target resource 40
target URI 40
TE header field 39
Trailer header field 40
Transfer-Encoding header field 28
transforming proxy 49
transparent proxy 11
tunnel 10

U

Upgrade header field 57
upstream 9
URI scheme
http 17
https 17
user agent 7

V

Via header field 47

Адреса авторов

Roy T. Fielding (editor)
Adobe Systems Incorporated
345 Park Ave
San Jose, CA 95110
USA
EMail: fielding@gbiv.com
URI: http://roy.gbiv.com/

Julian F. Reschke (editor)
greenbytes GmbH
Hafenweg 16
Muenster, NW 48155
Germany
EMail: julian.reschke@greenbytes.de
URI: http://greenbytes.de/tech/webdav/

Поделись записью