Что такое 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 дизайн]]