Spec-Zone.ru › HTTP

Сообщения

Сообщения HTTP

Сообщения HTTP — это механизм обмена данными между сервером и клиентом в протоколе HTTP. Существует два типа сообщений: запросы, отправляемые клиентом для запуска действия на сервере, и ответы — ответ сервера на запрос.

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

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

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

Примечание: Сообщения HTTP можно просматривать на вкладке Сеть в инструментах разработчика браузера или, например, выводить в консоль с помощью инструментов командной строки, таких как curl.

Структура сообщения HTTP

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

Requests and responses share a common structure in HTTP

Запросы и ответы имеют схожую структуру:

  1. Стартовая строка — это одна строка, описывающая версию HTTP, а также метод запроса или результат запроса.
  2. Необязательный набор заголовков HTTP, содержащих метаданные, описывающие сообщение. Например, запрос ресурса может указывать допустимые форматы этого ресурса, а в ответе могут быть заголовки, указывающие фактический возвращённый формат.
  3. Пустая строка, указывающая, что метаданные сообщения завершены.
  4. Необязательное тело, содержащее данные, связанные с сообщением. Это могут быть данные POST, отправляемые серверу в запросе, или ресурс, возвращаемый клиенту в ответе. Наличие тела в сообщении определяется стартовой строкой и заголовками HTTP.

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

Запросы HTTP

Рассмотрим следующий пример запроса HTTP POST, который отправляется после того, как пользователь отправляет форму на веб-странице:

POST /users HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49

name=FirstName+LastName&email=bsmth%40example.com

Стартовая строка в запросах HTTP/1.x (POST /users HTTP/1.1 в примере выше) называется «строкой запроса» и состоит из трёх частей:

<method> <request-target> <protocol>
<method>

Метод HTTP (также называемый глаголом HTTP) — это одно из набора определённых слов, описывающих смысл запроса и желаемый результат. Например, GET указывает, что клиент хочет получить ресурс в ответ, а POST означает, что клиент отправляет данные на сервер.

<request-target>

Цель запроса обычно представляет собой абсолютный или относительный URL и определяется контекстом запроса. Формат цели запроса зависит от используемого метода HTTP и контекста запроса. Более подробно это описано в разделе Цели запросов ниже.

<protocol>

Версия HTTP, определяющая структуру оставшейся части сообщения и указывающая версию, которую следует использовать для ответа. Почти всегда это HTTP/1.1, поскольку HTTP/0.9 и HTTP/1.0 устарели. В HTTP/2 и более поздних версиях версия протокола не включается в сообщения, так как определяется при установлении соединения.

Цели запросов

Цель запроса можно описать несколькими способами, но наиболее распространённая форма — «origin form». Ниже перечислены типы целей и случаи их использования:

  1. В origin form получатель объединяет абсолютный путь с информацией из заголовка Host. К пути можно добавить строку запроса с дополнительной информацией (обычно в формате key=value). Эта форма используется с методами GET, POST, HEAD и OPTIONS:

    GET /en-US/docs/Web/HTTP/Guides/Messages HTTP/1.1
    
  2. Абсолютная форма — это полный URL, включая полномочия, и она используется с GET при подключении к прокси-серверу:

    GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Messages HTTP/1.1
    
  3. Форма полномочий — это полномочия и порт, разделённые двоеточием (:). Она используется только с методом CONNECT при настройке HTTP-туннеля:

    CONNECT developer.mozilla.org:443 HTTP/1.1
    
  4. Форма со звёздочкой используется только с OPTIONS, когда нужно представить сервер целиком (*), а не именованный ресурс:

    OPTIONS * HTTP/1.1
    

Заголовки запросов

Заголовки — это метаданные, отправляемые вместе с запросом после стартовой строки и до тела. В приведённом выше примере отправки формы это следующие строки сообщения:

Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49

В HTTP/1.x каждый заголовок — это строка, не зависящая от регистра, за которой следует двоеточие (:) и значение, формат которого зависит от заголовка. Весь заголовок, включая значение, состоит из одной строки. В некоторых случаях эта строка может быть очень длинной, например, у заголовка Cookie.

Example of headers in an HTTP request

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

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

Тело запроса

Тело запроса — это часть запроса, содержащая информацию для сервера. Тело есть только у запросов PATCH, POST и PUT. В примере отправки формы эта часть и есть тело:

name=FirstName+LastName&email=bsmth%40example.com

Тело запроса с отправкой формы содержит относительно небольшой объём информации в виде пар key=value, но тело запроса может содержать и другие типы данных, которые ожидает сервер:

{
  "firstName": "Brian",
  "lastName": "Smith",
  "email": "bsmth@example.com",
  "more": "data"
}

или данные, состоящие из нескольких частей:

--delimiter123
Content-Disposition: form-data; name="field1"

value1
--delimiter123
Content-Disposition: form-data; name="field2"; filename="example.txt"

Text file contents
--delimiter123--

Ответы HTTP

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

HTTP/1.1 201 Created
Content-Type: application/json
Location: http://example.com/users/123

{
  "message": "New user created",
  "user": {
    "id": 123,
    "firstName": "Example",
    "lastName": "Person",
    "email": "bsmth@example.com"
  }
}

Стартовая строка (HTTP/1.1 201 Created выше) в ответах называется «строкой состояния» и состоит из трёх частей:

<protocol> <status-code> <reason-phrase>
<protocol>

Версия HTTP сообщения.

<status-code>

Числовой код состояния, указывающий, был ли запрос выполнен успешно или завершился ошибкой. Распространённые коды состояния: 200, 404 и 302.

<reason-phrase> Необязательно

Необязательный текст после кода состояния — это краткое, исключительно информационное описание состояния, помогающее человеку понять результат запроса. Иногда фраза причины заключается в скобки (например, «201 (Created)»), чтобы показать, что она необязательна.

Заголовки ответов

Заголовки ответов — это метаданные, отправляемые вместе с ответом. В HTTP/1.x каждый заголовок — это строка, не зависящая от регистра, за которой следует двоеточие (:) и значение, формат которого зависит от используемого заголовка.

Example of headers in an HTTP response

Как и в запросах, в ответах могут присутствовать самые разные заголовки; они делятся на следующие категории:

  • Заголовки ответов предоставляют дополнительный контекст сообщения или задают дополнительную логику для последующих запросов клиента. Например, такие заголовки, как Server, содержат информацию о программном обеспечении сервера, а Date указывает, когда был сформирован ответ. Они также могут содержать сведения о возвращаемом ресурсе, например его тип содержимого (Content-Type) или способ его кэширования (Cache-Control).
  • Заголовки представления, если у сообщения есть тело, описывают форму данных сообщения и применённую кодировку. Например, один и тот же ресурс может быть представлен в определённом типе медиа, например XML или JSON, локализован для конкретного письменного языка или географического региона и/или сжат либо закодирован иным способом для передачи. Это позволяет получателю понять, как восстановить ресурс в том виде, в котором он был до передачи по сети.

Тело ответа

В большинстве сообщений, отправляемых клиенту в ответ, присутствует тело. При успешном выполнении запроса тело ответа содержит данные, запрошенные клиентом в запросе GET. Если с запросом клиента возникли проблемы, в теле ответа обычно объясняется, почему запрос завершился ошибкой, и указывается, является ли эта ошибка постоянной или временной.

Тела ответов могут быть:

  • Содержать один ресурс, определяемый двумя заголовками: Content-Type и Content-Length, либо иметь неизвестную длину и передаваться частями с заголовком Transfer-Encoding, установленным в значение chunked.
  • Содержать несколько ресурсов — такие тела состоят из нескольких частей, каждая из которых содержит отдельные данные. Составные тела обычно используются в HTML-формах, но также могут отправляться в ответ на запросы диапазона.

Ответы с кодом состояния, который позволяет ответить на запрос без включения содержимого сообщения, например 201 Created или 204 No Content, не имеют тела.

Сообщения HTTP/2

В HTTP/1.x используются текстовые сообщения, которые легко читать и создавать, но у такого подхода есть несколько недостатков. Тела сообщений можно сжимать с помощью gzip или других алгоритмов сжатия, но не заголовки. Заголовки часто похожи или идентичны в ходе взаимодействия клиента и сервера, но повторяются в последующих сообщениях соединения. Известно множество очень эффективных способов сжатия повторяющегося текста, поэтому значительная экономия пропускной способности остаётся неиспользованной.

В HTTP/1.x также существует проблема, называемая блокировкой начала очереди (HOL): клиент должен дождаться ответа сервера, прежде чем отправить следующий запрос. Конвейеризация HTTP пыталась решить эту проблему, но из-за слабой поддержки и сложности используется редко, и её трудно реализовать правильно. Для параллельной отправки запросов необходимо открыть несколько соединений; установленные и активные соединения эффективнее новых из-за медленного старта TCP.

В HTTP/1.1 для параллельной отправки двух запросов нужно открыть два соединения:

Making two HTTP requests to a server in parallel

Это означает, что количество ресурсов, которые браузеры могут одновременно загружать и отображать, ограничено; обычно оно не превышает 6 параллельных соединений.

HTTP/2 позволяет одновременно использовать одно TCP-соединение для нескольких запросов и ответов. Для этого сообщения помещаются в бинарные кадры, а запросы и ответы передаются в нумерованном потоке внутри соединения. Кадры данных и заголовков обрабатываются отдельно, что позволяет сжимать заголовки с помощью алгоритма HPACK. Использование одного TCP-соединения для одновременной обработки нескольких запросов называется мультиплексированием.

Multiplexing requests and responses in HTTP/2 using a single TCP connection.

Запросы не обязательно выполняются последовательно: например, потоку 9 не нужно ждать завершения потока 7. Данные из нескольких потоков обычно чередуются в соединении, поэтому клиент может получать потоки 9 и 7 одновременно. Протокол позволяет задавать приоритет для каждого потока или ресурса. Ресурсы с низким приоритетом занимают меньше полосы пропускания, чем ресурсы с высоким приоритетом, когда передаются по разным потокам; также их можно фактически передавать последовательно в одном соединении, если сначала нужно обработать критически важные ресурсы.

В целом, несмотря на все улучшения и абстракции, добавленные по сравнению с HTTP/1.x, разработчикам практически не нужно менять API, используемые для работы с HTTP/2 вместо HTTP/1.x. Если HTTP/2 поддерживается и браузером, и сервером, он включается и используется автоматически.

Псевдозаголовки

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

  • :method — метод HTTP.
  • :scheme — схема целевого URI, обычно HTTP(S).
  • :authority — полномочия целевого URI.
  • :path — путь и параметры запроса целевого URI.

В ответах используется только один псевдозаголовок — :status, содержащий код ответа.

Чтобы выполнить запрос HTTP/2 и получить example.com, можно использовать nghttp, который выведет запрос в более удобном для чтения виде. Выполнить запрос можно этой командой: параметр -n отбрасывает загруженные данные, а -v включает подробный вывод, показывающий приём и передачу кадров:

nghttp -nv https://www.example.com

Если просмотреть вывод ниже, вы увидите время передачи и приёма каждого кадра:

[  0.123] <send|recv> <frame-type> <frame-details>

Нет необходимости подробно разбирать этот вывод, но обратите внимание на кадр HEADERS в формате [ 0.123] send HEADERS frame .... В строках после передачи заголовка появятся следующие строки:

[  0.447] send HEADERS frame ...
          ...
          :method: GET
          :path: /
          :scheme: https
          :authority: www.example.com
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.61.0

Если вы уже уверенно работаете с HTTP/1.x, это должно быть вам знакомо; понятия, рассмотренные в предыдущем разделе этого руководства, также применимы. Это бинарный кадр с запросом GET для example.com, преобразованный в удобный для чтения вид с помощью nghttp. Если просмотреть вывод команды дальше, в одном из потоков, полученных от сервера, можно увидеть псевдозаголовок :status:

[  0.433] recv (stream_id=13) :status: 200
[  0.433] recv (stream_id=13) content-encoding: gzip
[  0.433] recv (stream_id=13) age: 112721
[  0.433] recv (stream_id=13) cache-control: max-age=604800
[  0.433] recv (stream_id=13) content-type: text/html; charset=UTF-8
[  0.433] recv (stream_id=13) date: Fri, 13 Sep 2024 12:56:07 GMT
[  0.433] recv (stream_id=13) etag: "3147526947+gzip"
...

А если удалить из этого сообщения время и идентификатор потока, оно станет ещё более знакомым:

:status: 200
content-encoding: gzip
age: 112721

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

Заключение

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

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

Если вы понимаете семантику HTTP/1.1, у вас уже есть прочная основа для изучения HTTP/2 и HTTP/3. Главное различие заключается в том, как эта семантика реализуется на транспортном уровне. Изучив примеры и понятия из этого руководства, вы будете готовы работать с HTTP, понимать смысл сообщений и то, как приложения используют HTTP для отправки и получения данных.

См. также

  • Эволюция HTTP
  • Механизм обновления протокола
  • Термины глоссария:
    • HTTP
    • HTTP/2
    • QUIC

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Messages

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API