Питання 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]]