Что такое заголовки в HTTP и зачем они нужны?
Что такое заголовки в HTTP и зачем они нужны?
Теория: что такое HTTP-заголовки
HTTP-заголовки (headers) — это поля метаданных внутри HTTP-запросов и HTTP-ответов, которые задают контекст и параметры обработки сообщения, не являясь самим «контентом» ресурса. Заголовки позволяют согласовать поведение клиента, сервера и промежуточных узлов (прокси, кэши, балансировщики), оставаясь отдельным механизмом от URL и тела запроса.
В современных спецификациях HTTP семантика описывается отдельно от конкретной версии транспорта (HTTP/1.1, HTTP/2, HTTP/3), но идея заголовков сохраняется: передача структурированной «служебной» информации рядом с данными. На практике в HTTP/2 и HTTP/3 заголовки кодируются иначе (двоичные фреймы и сжатие), но логически это те же поля заголовков.
Структура сообщения HTTP/1.1
В HTTP/1.1 сообщение состоит из:
- стартовой строки (request line или status line),
- строк заголовков (0 или более),
- пустой строки (разделитель),
- тела (опционально).
Запрос (пример)
GET /products?category=books HTTP/1.1
Host: shop.example
Accept: application/json
User-Agent: ExampleBrowser/1.0
Ответ (пример)
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 52
Cache-Control: max-age=60
{ "items": [ { "id": 1, "name": "..." } ] }
Синтаксис заголовков
Базовая форма заголовка — field-name: field-value, где:
field-name— имя поля (например,Content-Type,Accept,Authorization),field-value— значение (например,application/json).
Имя поля заголовка нечувствительно к регистру, то есть Content-Type и content-type эквивалентны по смыслу, хотя в реальных системах иногда встречаются ошибки из-за неверных предположений в коде. Важно различать: заголовки — это не часть URL и не часть тела, а отдельный слой управления и метаданных.
Зачем нужны заголовки
Заголовки решают задачи, которые неудобно или неправильно решать через URL или тело:
- Согласование представления данных: какие форматы умеет клиент (
Accept), в каком формате отправлены данные (Content-Type), в какой кодировке и на каком языке. - Управление кэшированием и повторным использованием ответов: как долго ответ можно хранить, при каких условиях он считается свежим.
- Аутентификация и авторизация: как именно клиент доказывает право доступа (
Authorization), как сервер инициирует проверку (например,WWW-Authenticate). - Диагностика и маршрутизация: информация о целевом хосте, цепочке прокси, ограничениях, предпочтениях и возможностях клиента.
С практической точки зрения заголовки — это «контракт поведения» между сторонами: один и тот же URL может вернуть разные представления ресурса в зависимости от заголовков, а один и тот же ответ может по-разному кэшироваться и использоваться в зависимости от политики, заданной в заголовках.
Категории и примеры заголовков
Ниже приведена удобная группировка (не единственно возможная), чтобы быстрее ориентироваться.
Таблица: задачи и примеры полей
| Задача | Примеры заголовков | Что меняется в поведении |
|---|---|---|
| Формат данных | Content-Type, Accept, Accept-Language | Как интерпретировать тело и что предпочитает клиент |
| Кэширование | Cache-Control, ETag, If-None-Match | Можно ли хранить ответ и можно ли получить 304 вместо тела |
| Аутентификация | Authorization, WWW-Authenticate | Как подтверждаются права доступа |
| Передача тела | Content-Length, Transfer-Encoding | Как определить границы тела и способ передачи |
| Безопасность/политики | Strict-Transport-Security, Content-Security-Policy | Как браузер должен ограничивать опасное поведение |
| Информация о клиенте | User-Agent | Как сервер может адаптировать ответ (осторожно) |
Практика: типовые сценарии
Согласование формата (content negotiation)
Клиент может объявить, что предпочитает application/json, а сервер обязан явно указать, какой формат реально отправлен.
Запрос
GET /api/items HTTP/1.1
Host: api.example
Accept: application/json
Ответ
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 18
{ "items": [] }
Кэширование с ETag и 304
ETag — идентификатор версии ресурса; клиент может переспросить «изменилось ли», не скачивая тело заново.
Первый ответ
HTTP/1.1 200 OK
Content-Type: text/css
ETag: "v1"
Cache-Control: max-age=0
Content-Length: 12
body{...}
Повторный запрос
GET /styles.css HTTP/1.1
Host: site.example
If-None-Match: "v1"
Ответ, если не изменилось
HTTP/1.1 304 Not Modified
ETag: "v1"
Аутентификация через Bearer-токен
В API часто передаются учетные данные через Authorization: Bearer ....
GET /api/profile HTTP/1.1
Host: api.example
Accept: application/json
Authorization: Bearer eyJhbGciOi...
Пример в JavaScript (Fetch API)
Заголовки запроса задаются в headers, а значения ответных заголовков читаются через response.headers.get(...).
const response = await fetch("https://api.example/items", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer <token>"
},
body: JSON.stringify({ name: "item" })
});
const contentType = response.headers.get("content-type");
const data = await response.json();
Частые ошибки и как их избегать
- Путаница заголовков с query-параметрами: параметры в URL обычно описывают выбор ресурса/варианта запроса, заголовки — правила и контекст обработки сообщения.
- Несоответствие
Content-Typeи реального тела: если тело — JSON, должен быть указанContent-Type: application/json, иначе сервер/клиент может неверно распарсить данные. - Некорректная работа с
Content-Lengthи прокси: при ручной сборке HTTP-сообщений и нестандартных прокси-схемах особенно важно исключить двусмысленность границ тела. - Слепое доверие клиентским заголовкам:
User-Agent, «псевдо IP» в заголовках и любые «самоописания» клиента могут подделываться; для безопасности следует опираться на проверяемые механизмы.
Итого: HTTP-заголовки — это поля имя: значение в запросах и ответах, которые передают метаданные и управляют обработкой сообщения (формат, кэш, аутентификация, политики безопасности и прочее). Правильное понимание заголовков помогает отличать «данные ресурса» (тело) от «правил и контекста» (заголовки) и снижает риск ошибок в производительности и безопасности.