Как задать Content-Type в запросах cURL на PHP
Основные методы установки Content-Type в cURL
Наиболее эффективный и универсальный способ задать заголовок Content-Type в cURL - использовать опцию CURLOPT_HTTPHEADER с массивом строк, содержащих заголовки. Этот метод подходит для любых типов запросов (GET, POST, PUT, PATCH) и любых форматов данных (JSON, XML, форма, произвольный текст).
$ch = curl_init('https://example.com/api');
curl_setopt($ch, CURLOPT_POST, 1);
$data = ['key' => 'value'];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
Php curl content type (установка content-type в curl в php)
В этом примере явно указывается Content-Type: application/json, что гарантирует правильную интерпретацию данных сервером. Такой подход исключает автоматическое определение типа контента, которое может быть неверным (например, для JSON строки cURL может установить application/x-www-form-urlencoded).
Типичная ошибка: если не указать Content-Type, а передать строку JSON через CURLOPT_POSTFIELDS, cURL по умолчанию выставит application/x-www-form-urlencoded. Это приводит к тому, что сервер не распознает данные как JSON. Решение - всегда явно задавать заголовок через CURLOPT_HTTPHEADER.
Как Content-Type устанавливается автоматически при передаче данных через CURLOPT_POSTFIELDS?
Если в CURLOPT_POSTFIELDS передать строку (например, результат http_build_query()), cURL автоматически установит заголовок Content-Type: application/x-www-form-urlencoded. При передаче массива с элементами типа CURLFile заголовок станет multipart/form-data с автоматической границей. Это удобно для стандартных HTML-форм.
$ch = curl_init('https://example.com/form');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['name' => 'John', 'age' => 30]));
$response = curl_exec($ch);
Content type utf 8 php (кодировка utf-8 в content-type в php)
В данном случае ручная установка Content-Type не требуется. Однако при использовании нестандартных типов (JSON, XML) автоматический выбор не сработает.
Проблема: если передавать массив (не строку) без файлов, cURL может преобразовать его в строку вида key=value с Content-Type application/x-www-form-urlencoded. Если нужно отправить JSON, но случайно передать массив, данные будут закодированы как форма. Решение: всегда передавать строку JSON явно и указывать заголовок.
Цель использования: когда требуется отправить данные точно в том виде, как их понимает стандартная HTML-форма (например, для логина или поиска).
Как отправить JSON запрос с правильным Content-Type и авторизацией?
Используется CURLOPT_HTTPHEADER для указания Content-Type: application/json и, при необходимости, других заголовков (например, Authorization). Важно кодировать тело запроса через json_encode().
$url = 'https://api.example.com/data';
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . $token
];
$data = ['user' => ['name' => 'Alice', 'role' => 'admin']];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
Php content type html (content-type: text/html в php)
Ошибка: если в массиве $headers случайно указать два заголовка Content-Type (например, один из них добавляется автоматически), сервер может получить неверный тип. cURL не удаляет дубликаты, они отправляются как есть. Решение: перед установкой убедиться, что в массиве нет одноимённых заголовков.
Случай использования: работа с REST API, где почти всегда требуется указывать Content-Type: application/json.
Как отправить XML данные с Content-Type application/xml?
Аналогично JSON, только тело запроса формируется как XML-строка, а Content-Type устанавливается на application/xml или text/xml.
$xmlString = '<?xml version="1.0"?>value ';
$ch = curl_init('https://example.com/xml-endpoint');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlString);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/xml'
]);
$response = curl_exec($ch);
Php content type text (content-type: text/plain в php)
Проблема: если XML содержит символы, недопустимые в кодировке по умолчанию (например, UTF-8 не подходит для содержимого), сервер может отвергнуть запрос. Решение: задать явно кодировку в объявлении XML и в заголовке, например Content-Type: application/xml; charset=utf-8.
Цель: интеграция с SOAP-сервисами или старыми системами, использующими XML-RPC.
Как установить Content-Type для multipart/form-data при отправке файлов?
Если в массиве, переданном в CURLOPT_POSTFIELDS, содержатся объекты CURLFile, cURL автоматически устанавливает заголовок multipart/form-data и генерирует границу. Принудительное указание Content-Type через CURLOPT_HTTPHEADER не рекомендуется, так как граница будет отсутствовать.
$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, 1);
$file = new CURLFile('/path/to/file.jpg', 'image/jpeg', 'photo.jpg');
$data = ['photo' => $file, 'description' => 'My photo'];
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
Ошибка: если вместе с файлом передать и строку JSON (например, для поля metadata), cURL воспримет всю строку как multipart/form-data, но значение этого поля будет простой строкой, а не JSON. Сервер может ожидать JSON внутри части multipart. Решение: не смешивать типы без необходимости, либо кодировать JSON как строковое поле.
Случай использования: загрузка файлов на сервер через веб-формы.
Расширенные примеры установки Content-Type в cURL
Пример 1. Полный цикл отправки JSON с обработкой ответа и проверкой ошибок
$url = 'https://jsonplaceholder.typicode.com/posts';
$data = ['title' => 'foo', 'body' => 'bar', 'userId' => 1];
$jsonData = json_encode($data);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json'
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
echo "cURL Error: $error";
} else {
echo "HTTP Status: {$info['http_code']}\n";
echo "Response: $response";
}
HTTP Status: 201
Response: {
"title": "foo",
"body": "bar",
"userId": 1,
"id": 101
}
Здесь показана полная обработка: проверка на ошибки cURL, получение HTTP-статуса, вывод тела ответа. Установка Accept позволяет серверу вернуть данные в нужном формате.
Пример 2. Отправка данных с файлом и полями формы (multipart/form-data)
$url = 'https://httpbin.org/post';
$file = new CURLFile('/tmp/test.txt', 'text/plain', 'document.txt');
$fields = ['name' => 'Alice', 'file' => $file];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$decoded = json_decode($response, true);
echo "Form data: " . print_r($decoded['form'], true);
echo "Files: " . print_r($decoded['files'], true);
Form data: Array
(
[name] => Alice
)
Files: Array
(
[file] => Array
(
[name] => document.txt
[type] => text/plain
[size] => 100
)
)
Content-Type автоматически стал multipart/form-data; boundary=... . Принудительно изменять его не нужно - cURL сам формирует правильный заголовок.
Пример 3. PUT запрос с JSON данными и переопределением Content-Type
$url = 'https://api.example.com/resource/123';
$data = ['status' => 'updated'];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'If-Match: "abc123"'
],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
Для PUT запроса используется CURLOPT_CUSTOMREQUEST. Content-Type задаётся через CURLOPT_HTTPHEADER, как и в POST. Важно: не забыть кодировать данные.
Пример 4. Установка Content-Type с кодировкой (charset)
$ch = curl_init('https://example.com/text');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'Простой текст на русском');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/plain; charset=utf-8'
]);
$response = curl_exec($ch);
Иногда требуется указать кодировку вместе с типом контента. Это делается добавлением параметра charset к значению заголовка. cURL не проверяет корректность кодировки - она просто передаётся на сервер.
Пример 5. Проверка фактического отправленного Content-Type через curl_getinfo
$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => 'key=value',
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
// In httpbin response we can see headers sent
echo "Sent Content-Type: " . json_decode($response, true)['headers']['Content-Type'];
Sent Content-Type: application/x-www-form-urlencoded
Это полезно для отладки: можно убедиться, что заголовок отправлен корректно.