Механизм обновления протокола
Механизм обновления протокола
Протокол HTTP/1.1 предоставляет специальный механизм, который может использоваться для обновления уже установленного соединения до другого протокола, используя поле заголовка Upgrade.
Этот механизм является необязательным; он не может быть использован для настойчивого изменения протокола. Реализации могут выбрать игнорирование обновления, даже если поддерживают новый протокол, и на практике этот механизм используется в основном для инициализации подключения WebSocket.
Обратите также внимание, что HTTP/2 явно запрещает использование этого механизма; он специфичен для HTTP/1.1.
Обновление соединений HTTP/1.1
Поле заголовка Upgrade используется клиентами для приглашения сервера переключиться на один из перечисленных протоколов, в порядке убывания предпочтения.
Поскольку Upgrade является заголовком «перепрыгивания», его также необходимо указать в поле заголовка Connection. Это означает, что типичный запрос, включающий Upgrade, будет выглядеть примерно так:
GET /index.html HTTP/1.1 Host: www.example.com Connection: upgrade Upgrade: example/1, foo/2
Другие заголовки могут потребоваться в зависимости от запрошенного протокола; например, обновления WebSocket позволяют добавлять дополнительные заголовки для настройки деталей подключения WebSocket, а также для обеспечения определенной степени безопасности при открытии подключения. Более подробную информацию см. в разделе Обновление до подключения WebSocket.
Если сервер решит обновить соединение, он отправит ответ со статусом 101 Switching Protocols и заголовком Upgrade, указывающим на протокол(ы), на который(е) происходит переключение. Если он не сможет (или не захочет) обновить соединение, он проигнорирует заголовок Upgrade и отправит обычный ответ (например, 200 OK).
Сразу после отправки кода состояния 101, сервер может начать использовать новый протокол, выполнив любые дополнительные необходимые процедуры рукопожатия, специфичные для протокола. По сути, соединение становится двусторонним каналом сразу после завершения ответа об обновлении, и запрос, инициировавший обновление, может быть завершен по новому протоколу.
Общие применения этого механизма
Здесь мы рассмотрим наиболее распространённые случаи использования заголовка Upgrade.
Обновление до подключения WebSocket
Наиболее распространённый случай обновления HTTP-соединения — использование WebSocket, которые всегда реализуются путём обновления HTTP- или HTTPS-соединения. Имейте в виду, что если вы открываете новое соединение с помощью API WebSocket или любой библиотеки, реализующей WebSocket, большая часть или вся эта работа выполняется за вас. Например, открытие соединения WebSocket так же просто, как:
webSocket = new WebSocket("ws://destination.server.ext", "optionalProtocol");
Конструктор WebSocket() выполняет всю работу по созданию начального HTTP/1.1-соединения, а затем обрабатывает процесс рукопожатия и обновления за вас.
Примечание: Вы также можете использовать схему URL "wss://" для открытия защищённого WebSocket-соединения.
Если вам необходимо создать WebSocket-соединение с нуля, вам придётся самим обработать процесс рукопожатия. После создания начальной HTTP/1.1-сессии вам необходимо запросить обновление, добавив в стандартный запрос заголовки Upgrade и Connection, как показано ниже:
Connection: Upgrade Upgrade: websocket
Заголовки, специфичные для WebSocket
В процессе обновления WebSocket участвуют следующие заголовки. Помимо заголовков Upgrade и Connection, остальные обычно являются необязательными или обрабатываются браузером и сервером при их взаимодействии.
Sec-WebSocket-Extensions
Указывает один или несколько WebSocket-расширений уровня протокола, предлагаемых серверу. Использование более одного заголовка Sec-WebSocket-Extension в запросе разрешено; результат такой же, как если бы вы включили все перечисленные расширения в один такой заголовок.
Sec-WebSocket-Extensions: extensions
extensions-
Список расширений, которые необходимо запросить (или с которыми необходимо согласиться), разделённый запятыми. Эти расширения должны быть выбраны из реестра имён расширений WebSocket IANA. Расширения, которые принимают параметры, делают это с использованием разделителя «точка с запятой».
Например:
Sec-WebSocket-Extensions: superspeed, colormode; depth=16
Sec-WebSocket-Key
Предоставляет серверу информацию, необходимую для подтверждения права клиента на запрос обновления до WebSocket. Этот заголовок может использоваться, когда клиенты (HTTP) хотят обновить соединение, чтобы предложить некоторую степень защиты от злоупотреблений. Значение ключа вычисляется с помощью алгоритма, определённого в спецификации WebSocket, поэтому это не обеспечивает безопасность. Вместо этого он помогает предотвратить случайный или злонамеренный запрос WebSocket-соединения со стороны клиентов, не являющихся WebSocket-клиентами. По сути, этот ключ подтверждает, что «Да, я действительно хочу открыть WebSocket-соединение».
Этот заголовок автоматически добавляется клиентами, которые его используют; его нельзя добавить с помощью метода XMLHttpRequest.setRequestHeader().
Sec-WebSocket-Key: key
key-
Ключ для этого запроса на обновление. Клиент добавляет его, если пожелает, а сервер включит в ответ свой собственный ключ, который клиент проверит перед предоставлением ответа об обновлении.
Заголовок ответа сервера Sec-WebSocket-Accept будет содержать значение, вычисленное на основе указанного key.
Sec-WebSocket-Protocol
Заголовок Sec-WebSocket-Protocol определяет один или несколько WebSocket-протоколов, которые вы хотите использовать, в порядке предпочтения. Первый протокол, поддерживаемый сервером, будет выбран и возвращён сервером в заголовке Sec-WebSocket-Protocol, включённом в ответ. Вы можете использовать этот заголовок несколько раз; результат такой же, как если бы вы использовали разделенный запятыми список идентификаторов подпротоколов в одном заголовке.
Sec-WebSocket-Protocol: subprotocols
subprotocols-
Список подпротоколов, разделённый запятыми, в порядке предпочтения. Подпротоколы могут быть выбраны из реестра имён подпротоколов WebSocket IANA или могут быть пользовательским именем, согласованным клиентом и сервером.
Sec-WebSocket-Version
Заголовок запроса
Указывает версию WebSocket-протокола, которую хочет использовать клиент, чтобы сервер мог подтвердить, поддерживается ли эта версия на стороне сервера.
Sec-WebSocket-Version: version
version-
Версия WebSocket-протокола, которую клиент хочет использовать при общении с сервером. Это число должно быть наиболее последней возможной версией, указанной в реестре версий WebSocket IANA. Последней окончательной версией WebSocket-протокола является версия 13.
Заголовок ответа
Если сервер не может общаться с использованием указанной версии WebSocket-протокола, он ответит ошибкой (например, 426 Upgrade Required), которая включает в свои заголовки заголовок Sec-WebSocket-Version с разделенным запятыми списком поддерживаемых версий протокола. Если сервер поддерживает запрошенную версию протокола, заголовок Sec-WebSocket-Version в ответе не включён.
Sec-WebSocket-Version: supportedVersions
supportedVersions-
Список версий WebSocket-протокола, поддерживаемых сервером, разделённый запятыми.
Только заголовки ответа
Ответ сервера может содержать следующие заголовки.
Sec-WebSocket-Accept
Включён в сообщении ответа сервера во время процесса открытия рукопожатия, когда сервер готов инициировать WebSocket-соединение. Он появляется не более одного раза в заголовках ответа.
Sec-WebSocket-Accept: hash
hash-
Если был предоставлен заголовок
Sec-WebSocket-Key, значение этого заголовка вычисляется путём взятия значения ключа, конкатенации строки «258EAFA5-E914-47DA-95CA-C5AB0DC85B11» к нему, взятия хэша SHA-1 от этой конкатенированной строки, что приводит к значению из 20 байт. Затем это значение кодируется в Base64 для получения значения данного свойства.
Ссылки
- WebSocket API
- HTTP
- Спецификации и RFC:
© 2005–2022 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism