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