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

Что такое Content-Type header?

Сервер должен знать, как прочитать данные из запроса. Без Content-Type сервер не поймёт, как десериализовать байты.

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

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:

  1. Приходит запрос с Content-Type: application/json
  2. Spring перебирает конвертеры (Jackson, Gson и т.д.)
  3. Метод canRead(clazz, mediaType) возвращает true
  4. Запускается чтение и маппинг в 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/json UTF-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 выбирается на основе:

  1. Заголовка Content-Type из запроса
  2. Зарегистрированных конвертеров в приложении
  3. Метода 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 дизайн]]