Що таке Content-Type header?
Сервер повинен знати, як прочитати дані із запиту. Без Content-Type сервер не зрозуміє, як десеріалізувати байти.
Junior Level
Content-Type — це заголовок HTTP, який каже серверу, в якому форматі надсилаються дані.
Приклади:
Content-Type: application/json — дані у форматі JSON
Content-Type: application/xml — дані у форматі XML
Content-Type: text/plain — звичайний текст
Content-Type: multipart/form-data — форма з файлами
Навіщо це потрібно?
Сервер повинен знати, як прочитати дані із запиту. Без Content-Type сервер не зрозуміє, як десеріалізувати байти.
Приклад запиту:
POST /users
Content-Type: application/json
{"name": "Ivan", "age": 30}
Поширені медіа-типи:
| Тип | Опис |
| ———————————– | —————- |
| application/json | JSON дані |
| application/xml | XML дані |
| text/html | HTML сторінка |
| multipart/form-data | Форма з файлами |
| application/x-www-form-urlencoded | Дані форми |
Middle Level
Content-Type у Spring MVC
За обробку Content-Type відповідають HttpMessageConverter:
- Приходить запит із
Content-Type: application/json - Spring перебирає конвертери (Jackson, Gson і т.д.)
- Метод
canRead(clazz, mediaType)повертаєtrue - Запускається читання і маппінг у Java-об’єкт
Безпека і MIME Sniffing
X-Content-Type-Options: nosniff
Браузери іноді намагаються “вгадати” тип контенту, ігноруючи заголовок. MIME Sniffing — механізм браузера: він намагається визначити тип контенту за вмістом, ігноруючи Content-Type. Корисно для зворотної сумісності, але створює XSS-уразливості.
Ризик: Користувач завантажив картинку, яка насправді JavaScript. Браузер може її виконати.
Рішення: Завжди передавайте X-Content-Type-Options: nosniff.
Boundary у Multipart
При multipart/form-data заголовок містить унікальний роздільник:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Цей роздільник використовується для парсингу тіла запиту на окремі частини.
Прикордонні випадки
- Missing Content-Type: Якщо клієнт не надіслав заголовок — повернути 415 Unsupported Media Type. Не намагайтеся вгадувати тип
- Custom MIME Types: Для версіонування використовуйте свої типи:
application/vnd.mycompany.v1+json
Продуктивність
- Charset: Для
application/jsonUTF-8 є дефолтним за RFC 8259, томуcharset=utf-8опціональний. Дляtext/*типів вказання charset обов’язкове, оскільки дефолт —iso-8859-1. - Binary Formats: У Highload-системах використовують
application/x-protobufабоapplication/octet-stream— Protobuf зазвичай у 3-10x швидше JSON при парсингу (залежить від розміру payload і мови). Бінарний формат не потребує лексичного розбору, немає парсингу рядків-ключів — числові теги полів.
Senior Level
Коли Content-Type можна не вказувати
GET-запити без тіла, DELETE без тіла. Для запитів з тілом (POST, PUT, PATCH) — обов’язковий.
Процес вибору конвертера
У Spring MVC HttpMessageConverter обирається на основі:
- Заголовка
Content-Typeіз запиту - Зареєстрованих конвертерів у додатку
- Методу
canRead(clazz, mediaType)
Multipart/Related vs Multipart/Form-Data
- Multipart/Form-Data: Для завантаження файлів через форми
- Multipart/Related: Якщо потрібно надіслати об’єкт (JSON) і пов’язаний з ним бінарний файл (картинку) в одному запиті. Ефективніше двох окремих запитів
Продуктивність і Highload
- Charset Overhead: Вказання кодування запобігає спробам проксі перекодувати текст
- Binary Formats: Protobuf зазвичай у 3-10x швидше JSON при парсингу (залежить від розміру payload і мови). Бінарний формат не потребує лексичного розбору, немає парсингу рядків-ключів — числові теги полів.
- Multipart/Related: Ефективніше для відправки JSON + бінарний файл в одному запиті
Діагностика
- Curl Debugging:
curl -v -H "Content-Type: application/json" -d '{"key":"val"}' ...— база для налагодження API - Postman/Insomnia Pitfalls: Ці інструменти часто додають
Content-Typeавтоматично. При тестуванні “чистого” API вимикайте автозаповнення - 415 Unsupported Media Type: Якщо сервер не підтримує надісланий тип — повертайте 415, не намагайтеся вгадати
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- Content-Type вказує серверу формат даних у тілі запиту:
application/json,application/xml,multipart/form-data - Для запитів з тілом (POST, PUT, PATCH) Content-Type обов’язковий; для GET/DELETE без тіла — не потрібен
- У Spring MVC за обробку відповідають HttpMessageConverter (Jackson, Gson і т.д.)
- X-Content-Type-Options: nosniff запобігає MIME Sniffing і XSS-атакам
- multipart/form-data використовує boundary-роздільник для парсингу тіла на частини
- Missing Content-Type → повернути 415 Unsupported Media Type, не вгадувати
- Binary Formats (Protobuf) у 3-10x швидше JSON при парсингу
Часті уточнюючі запитання:
- Навіщо потрібен X-Content-Type-Options: nosniff? — Запобігає MIME Sniffing, коли браузер «вгадує» тип і виконує JS
- Як Spring обирає конвертер? — За Content-Type запиту → перевіряє canRead(clazz, mediaType) → перший підходящий
- Коли Content-Type можна не вказувати? — Для GET і DELETE без тіла; для POST/PUT/PATCH — обов’язковий
- Що таке Multipart/Related? — Відправлення JSON + пов’язаного бінарного файлу в одному запиті, ефективніше двох запитів
Червоні прапорці (НЕ говорити):
- «Content-Type і Accept — одне й те саме» — Content-Type = що надсилаю, Accept = що хочу отримати
- «Content-Type потрібен для GET-запитів» — GET без тіла не вимагає Content-Type
- «Сервер може вгадати тип контенту» — потрібно повернути 415, не вгадувати
- «charset=utf-8 обов’язковий для JSON» — UTF-8 є дефолтним за RFC 8259, опціональний
Пов’язані теми:
- [[Що таке Accept header]]
- [[Як організувати версіонування REST API]]
- [[Що таке REST]]
- [[Які HTTP статус коди ви знаєте]]
- [[Що таке RESTful API дизайн]]