Вопрос 17 · Раздел 6

Что такое Accept header?

Сервер вернёт 406 Not Acceptable — "Я не могу ответить в формате, который вы просите".

Версии по языкам: English Russian Ukrainian

Junior Level

Accept — это заголовок HTTP, который говорит серверу, в каком формате клиент хочет получить ответ.

Примеры:

Accept: application/json        — хочу JSON
Accept: application/xml         — хочу XML
Accept: text/html               — хочу HTML
Accept: */*                     — подойдёт любой формат

Разница с Content-Type:

  • Content-Type — формат данных, которые отправляю
  • Accept — формат данных, которые хочу получить

Пример запроса:

GET /users/1
Accept: application/json

// Ответ сервера:
{"id": 1, "name": "Ivan", "age": 30}

Что будет, если сервер не поддерживает запрошенный формат?

Сервер вернёт 406 Not Acceptable — “Я не могу ответить в формате, который вы просите”.


Middle Level

Content Negotiation в Spring

Алгоритм согласования контента:

  1. Клиент присылает Accept: application/json
  2. Spring ищет методы контроллера с produces = "application/json"
  3. Проверяет наличие HttpMessageConverter, который может записать (write) данный тип
  4. Если совпадений нет — возвращается 406 Not Acceptable

Коэффициенты качества (q-values)

Заголовок Accept поддерживает веса приоритетов:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  • text/html — приоритет 1.0 (по умолчанию)
  • application/xml — приоритет 0.9
  • */* (всё остальное) — 0.8
    • В примере выше */* имеет q=0.8 — это значение конкретного браузера. Клиент может задать любой q от 0.0 до 1.0.

Зачем? Это позволяет реализовать Graceful Degradation (постепенная деградация — если сервер не может отдать предпочтительный формат, он отдаст альтернативный). Мобильное приложение просит application/json;q=1.0 и text/plain;q=0.5.

Производительность и Кэширование

The Vary Header

Если эндпоинт отдаёт разные форматы (JSON/XML) на один URL в зависимости от Accept, RFC 7231 требует возвращать Vary: Accept, если контент зависит от этого заголовка и ответ может быть кеширован. Без Vary CDN/прокси могут отдать неправильный формат.

Почему? Чтобы кэш (Nginx/CDN) не отдал JSON-ответ пользователю, запросившему XML.

Edge Cases

  • Accept-Charset и Accept-Encoding: Не путайте их. Accept — про формат данных, Accept-Charset — про кодировку, Accept-Encoding — про сжатие (gzip/brotli)
  • Браузерные Wildcards: Браузеры часто присылают Accept: */*. Spring выберет первый подходящий конвертер (обычно JSON)

Диагностика

  • 406 Not Acceptable Analysis: Всплеск 406 = клиент просит формат, который вы не реализовали (или случайно удалили конвертер)
  • ContentNegotiationManager: Можно настроить приоритет: расширение в пути (.json) → параметр (?format=json) → заголовок Accept. На Senior-уровне рекомендуется полагаться только на заголовки

Senior Level

Когда Accept header не нужен

  1. API с одним фиксированным форматом (только JSON)
  2. Внутренние микросервисы — формат зафиксирован контрактом
  3. Когда Content Negotiation добавляет оверхед без пользы

Content Negotiation — глубокий взгляд

Content Negotiation — это процесс, при котором сервер определяет лучший формат ответа для клиента.

Spring ContentNegotiationManager

Можно настроить приоритет выбора:

  1. Расширение в пути (.json)
  2. Параметр запроса (?format=json)
  3. Заголовок Accept

Рекомендация: На Senior-уровне полагайтесь только на заголовки. Расширения в пути и параметры запроса создают проблемы с кэшированием и семантикой URL.

Vendor MIME Types для версионирования

Использование application/vnd.mycompany.v1+json — отличный способ версионирования:

  • Позволяет кэшировать разные версии API по одному URI
  • Если кэш учитывает заголовок Accept, разные версии не перемешаются

Производительность

  • Vary: Accept рекомендуется при поддержке нескольких форматов — без этого CDN может отдать неверный формат из кэша
  • Vendor MIME Types позволяют версионировать каждую сущность независимо
  • Negative Caching: CDN может кешировать 406 ответы, защищая бэкенд от повторных запросов неподдерживаемых форматов

Диагностика и Мониторинг

  • 406 Analysis: Всплеск 406 означает, что клиент обновился и просит формат, который вы ещё не реализовали
  • Converter Order: Порядок регистрации конвертеров важен — Spring выбирает первый подходящий
  • Browser Behavior: Браузеры часто шлют Accept: */*, что может привести к неожиданному выбору формата. Тестируйте с реальными User-Agent заголовками

🎯 Шпаргалка для интервью

Обязательно знать:

  • Accept указывает серверу формат, в котором клиент хочет получить ответ: application/json, application/xml
  • Content-Type = что отправляю, Accept = что хочу получить
  • q-values (коэффициенты качества): Accept: application/json;q=1.0,text/plain;q=0.5 — приоритеты от 0.0 до 1.0
  • 406 Not Acceptable — сервер не поддерживает запрошенный формат
  • Vary: Accept обязателен при поддержке нескольких форматов — без него CDN отдаст неверный формат из кэша
  • Vendor MIME Types (application/vnd.mycompany.v1+json) — способ версионирования API
  • Spring ContentNegotiationManager: приоритет — расширение пути → query-параметр → заголовок Accept

Частые уточняющие вопросы:

  • Что делает Vary: Accept? — Указывает кэшу, что ответ зависит от заголовка Accept; без Vary CDN отдаст JSON вместо XML
  • Зачем нужны q-values? — Graceful Degradation: если сервер не может отдать приоритетный формат, отдаст альтернативный
  • Почему не стоит использовать расширения (.json) для Content Negotiation? — Создают проблемы с кэшированием и семантикой URL
  • Как версионировать через Accept? — Vendor MIME Types: application/vnd.myapi.v2+json, кэш учитывает Accept

Красные флаги (НЕ говорить):

  • «Accept и Content-Type — одно и то же» — Accept = ожидаемый ответ, Content-Type = формат запроса
  • «Браузеры всегда шлют конкретный Accept» — браузеры часто шлют Accept: */*
  • «406 — это ошибка сервера» — 406 = клиент просит формат, который сервер не поддерживает
  • «Vary: Accept не нужен» — без Vary CDN может отдать JSON-ответ клиенту, запросившему XML

Связанные темы:

  • [[Что такое Content-Type header]]
  • [[Как организовать версионирование REST API]]
  • [[Какие HTTP статус коды вы знаете]]
  • [[Что такое REST]]
  • [[Что такое HATEOAS]]