Content Negotiation: заголовки Accept

Content Negotiation: заголовки Accept

Один и тот же URL может отдавать данные в разных форматах. /api/user может вернуть JSON для скрипта, XML для интеграции или даже HTML-страницу для браузера (хотя это редкость). Механизм, который позволяет клиенту и серверу договориться о формате — Content Negotiation.

Как работает согласование контента

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

Клиент → Accept: application/json, text/xml;q=0.8
Сервер → Content-Type: application/json

Согласование может происходить по:

  • Формату данных (MIME-тип) — заголовки Accept и Content-Type.
  • ЯзыкуAccept-Language и Content-Language.
  • КодировкеAccept-Encoding и Content-Encoding.
  • Набору символовAccept-Charset (почти не используется, UTF-8 стал стандартом).

Accept: какой формат данных

Accept перечисляет MIME-типы, которые клиент готов обработать. Приоритеты задаются через q (quality factor, 0–1):

Accept: application/json, text/html;q=0.9, */*;q=0.1

Это означает: «лучше JSON (q=1.0 по умолчанию), если нет — HTML (q=0.9), на худой конец что угодно (q=0.1)».

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

Запрос:  Accept: application/json, text/html;q=0.9
Сервер может отдать: {"data": ...}  → Content-Type: application/json
Сервер может отдать только HTML:    → Content-Type: text/html (игнорирует q)

Accept-Language: язык ответа

Клиент перечисляет предпочитаемые языки:

Accept-Language: ru, en;q=0.9, de;q=0.5

Сервер выбирает доступный язык и указывает в Content-Language:

Content-Language: ru

Многие сайты игнорируют Accept-Language и определяют язык по URL (/ru/, /en/), cookie или геолокации. Но для API и headless-клиентов заголовок Accept-Language — стандартный способ указать язык.

Accept-Encoding: сжатие

Клиент сообщает, какие алгоритмы сжатия поддерживает:

Accept-Encoding: gzip, deflate, br

Сервер выбирает и сжимает ответ:

Content-Encoding: br

Brotli (br) — современный алгоритм, эффективнее gzip на 20–30% для текстовых данных. Поддерживается всеми современными браузерами. Сервер не обязан сжимать — но хороший тон сжимать текстовые ответы (HTML, CSS, JS, JSON, SVG).

Когда Content Negotiation не нужен

Для большинства современных API Content Negotiation не нужна: API отдаёт только JSON (или только XML для SOAP). Заголовок Accept: application/json браузер отправляет по умолчанию для fetch(), а curl — нет (поэтому некоторые API ломаются в curl, если сервер требует Accept).

Альтернативный подход — указывать формат в URL: /api/user.json, /api/user.xml. Проще, нагляднее, не зависит от заголовков. Но считается менее «REST-овым».

Проверь себя

  1. Что означает q=0.8 в заголовке Accept?
  2. Какой заголовок отвечает сервер, чтобы сообщить, на каком языке ответ?
  3. Почему серверы сжимают HTML, CSS, JS, но не изображения?
<details> <summary>Ответы</summary>
  1. Приоритет (quality factor). 1.0 — максимальный (по умолчанию), 0.8 — ниже. Сервер сначала попробует отдать формат с q=1.0, если его нет — с q=0.8.
  2. Content-Language. Например, Content-Language: ru.
  3. Изображения (PNG, JPEG, WebP) уже сжаты своими кодек-алгоритмами. Повторное сжатие (gzip/brotli) не уменьшит размер и потратит CPU впустую.
</details>

Что унести с урока

  • Content Negotiation — механизм согласования формата, языка и кодировки между клиентом и сервером.
  • Клиент: Accept, Accept-Language, Accept-Encoding. Сервер: Content-Type, Content-Language, Content-Encoding.
  • q-параметр задаёт приоритет формата или языка.
  • Для современных REST API Content Negotiation обычно не нужна — используется только JSON.

В последнем уроке модуля — Connection management и Keep-Alive: как HTTP оптимизирует TCP-соединения.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике