HTTPQUERY
Русский

Content-Type

Применение

Заголовок Content-Type сообщает клиенту (или серверу, если речь о телах запросов) медиатип содержащегося контента. Медиатип определяет, как получатель разбирает и отображает тело. Без этого заголовка клиенты прибегают к MIME-сниффингу, что порождает угрозы безопасности и непредсказуемое поведение.

Примечание

Accept объявляет, что клиент хочет получить. Content-Type объявляет, что отправляется. Accept встречается в запросах. Content-Type встречается и в запросах (когда есть тело), и в ответах. У GET-запросов обычно нет тела, и Content-Type им не нужен. Запросы POST и PUT с телом требуют этого заголовка.

Медиатип состоит из типа верхнего уровня и подтипа, разделённых косой чертой, за которыми необязательно следуют параметры. Заголовок запроса Accept работает совместно с Content-Type при согласовании содержимого, позволяя клиенту выразить предпочитаемые медиатипы до того, как сервер сделает выбор.

Серверы и промежуточные узлы иногда применяют Content-Encoding (например, gzip или br) перед передачей. Заголовок Content-Type всегда описывает исходный медиатип до кодирования, а не закодированный формат.

Заголовок MIME-Version восходит к происхождению MIME-типов из электронной почты и встречается в некоторых HTTP-сообщениях, хотя HTTP не требует его для обработки медиатипов.

media-type

Значение медиатипа следует формату type/subtype, зарегистрированному в IANA. Распространённые типы включают text/html, application/json, image/png и application/octet-stream. Полный реестр поддерживается IANA.

charset

Параметр charset задаёт кодировку символов для текстовых медиатипов. UTF-8 — доминирующая кодировка в вебе.

Content-Type: text/html; charset=UTF-8

boundary

Параметр boundary обязателен для медиатипов multipart/*. Строка boundary разделяет каждую часть составного тела. Значение boundary не должно встречаться ни в одной из частей тела.

Content-Type: multipart/form-data; boundary=----FormBoundary

Пример

Сервер возвращает HTML-страницу в кодировке UTF-8. Браузер использует медиатип, чтобы отобразить содержимое как веб-страницу, и charset, чтобы правильно декодировать текст.

Content-Type: text/html; charset=UTF-8

API возвращает JSON-ответ. Медиатип application/json указывает клиенту разбирать тело как JSON.

Content-Type: application/json

Ответ API с ошибкой использует медиатип application/problem+json, чтобы обозначить структурированную полезную нагрузку с описанием проблемы.

Content-Type: application/problem+json

CDN на лету преобразует HTML-страницу в Markdown, когда клиент отправляет Accept: text/markdown. Ответ несёт text/markdown в качестве типа содержимого, сигнализируя, что тело — это Markdown, а не HTML.

Content-Type: text/markdown; charset=utf-8

ИИ-агенты и Content-Type

Провайдеры CDN вроде Cloudflare возвращают Content-Type: text/markdown вместе с заголовком x-markdown-tokens, оценивающим количество токенов в преобразованном документе. Агенты используют тип содержимого, чтобы выбрать правильный парсер, а оценку токенов — чтобы управлять бюджетом контекстного окна.

Загрузка файла использует multipart/form-data со строкой boundary, разделяющей поля формы и данные файла внутри тела запроса.

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

Сервер отдаёт двоичный файл на скачивание. Тип application/octet-stream обозначает сырые двоичные данные и обычно сочетается с заголовком Content-Disposition со значением attachment.

Content-Type: application/octet-stream

Ответ multipart/byteranges отдаёт несколько байтовых диапазонов одного ресурса. У каждой части есть собственные заголовки Content-Type и Content-Range.

Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

Диагностика

Сбои отображения и ошибки разбора часто восходят к отсутствующему или неверному заголовку Content-Type.

Отсутствие параметра charset приводит к искажённому тексту. Когда charset не объявлен, браузеры откатываются к кодировке по умолчанию (часто ISO-8859-1). Символы вне ASCII превращаются в кракозябры. Добавьте параметр charset явно: Content-Type: text/html; charset=UTF-8. В nginx:

charset utf-8;

В Apache:

AddDefaultCharset UTF-8

Браузер применяет MIME-сниффинг, несмотря на корректный Content-Type. Браузеры иногда игнорируют объявленный тип и анализируют содержимое тела, чтобы определить тип. Такое поведение создаёт векторы XSS-атак, когда загруженный пользователями контент отдаётся как HTML. Добавьте заголовок X-Content-Type-Options со значением nosniff, чтобы заблокировать MIME-сниффинг:

X-Content-Type-Options: nosniff

API возвращает text/html вместо application/json. Клиенты, разбирающие JSON от API, получают HTML-страницы ошибок или стандартные ответы фреймворка. Так происходит, когда обработчик ошибок или обратный прокси перехватывает ответ и заменяет тело, не обновив Content-Type. Проверьте всю цепочку ответа: сервер-источник, фреймворк приложения, обратный прокси и CDN. В Express.js вызов res.json() устанавливает корректный заголовок автоматически. В Django возвращайте JsonResponse вместо HttpResponse.

Несовпадение multipart-границы ломает загрузку файлов. Строка boundary, объявленная в заголовке Content-Type, должна совпадать с разделителем, используемым в теле запроса. Несовпадение приводит к тому, что сервер не может разобрать составное тело. Изучите сырой запрос во вкладке Network в DevTools в разделах Headers и Payload. Избегайте ручной установки boundary при использовании fetch() или XMLHttpRequest с объектами FormData. Браузер генерирует корректную границу автоматически, когда заголовок Content-Type в запросе опущен.

Стандартный Content-Type фреймворка перекрывает явную настройку. Некоторые фреймворки устанавливают Content-Type после выполнения кода приложения. Промежуточное ПО в Express.js, Django или Spring Boot может сбросить заголовок. Проверьте порядок выполнения промежуточного ПО. В Express.js убедитесь, что res.type() или res.set(‘Content-Type’, …) вызывается после всего промежуточного ПО, изменяющего заголовки.

Диагностика проблем с Content-Type через DevTools. Откройте вкладку Network в DevTools браузера, выберите запрос и изучите значение Content-Type в разделе Response Headers. Сравните объявленный тип с фактическим содержимым тела, показанным во вкладке Response или Preview. Используйте curl -I https://example.re/api/data, чтобы проверить заголовки из командной строки без вмешательства браузера.