← К заметкам

Заметки

REST 3.0: JSON правильный, а заголовок cURL не отправился

При разборе InvalidJsonException легко зациклиться на содержимом JSON. Но ошибка бывает раньше: строка подготовлена правильно, а HTTP-запрос собран неверно.

Например, эта запись синтаксически похожа на настройку cURL, но не связывает опцию с её значением:

CURLOPT_HTTPHEADER, ['Content-Type: application/json'],

В массиве появляются два элемента с числовыми ключами. Нужна пара CURLOPT_HTTPHEADER => [...]. Некорректный массив опций может быть отклонён самим PHP/cURL ещё до отправки запроса.

Запрос к REST 3.0

Фрагмент для PHP 7.3+ с расширением cURL. Переменная $s_url содержит полный URL вебхука к tasks.task.chat.message.send, а $i_task_id — целочисленный ID задачи. В URL этого метода нужен путь /rest/api/.

$ar_payload = ['fields' => ['taskId' => $i_task_id, 'text' => 'Документ подготовлен']];
$s_json = json_encode($ar_payload, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
$curl_handle = curl_init($s_url);

curl_setopt_array($curl_handle, [
	CURLOPT_POST => true,
	CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
	CURLOPT_POSTFIELDS => $s_json,
	CURLOPT_RETURNTRANSFER => true,
	CURLOPT_CONNECTTIMEOUT => 10,
	CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($curl_handle);
if ($response === false) {
	$s_error = curl_error($curl_handle);
	curl_close($curl_handle);
	throw new RuntimeException($s_error);
}

$i_status = (int) curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
curl_close($curl_handle);

echo 'HTTP: ' . $i_status . PHP_EOL;
echo $response;

Здесь отдельно видны ошибка транспорта, HTTP-статус и тело ответа. JSON кодируется один раз, в CURLOPT_POSTFIELDS передаётся строка. Передача PHP-массива включила бы другой формат тела запроса.

REST 3.0 ожидает JSON с Content-Type: application/json. Вызов из адресной строки браузера не воспроизводит такой POST-запрос.

Документация: REST 3.0; curl_setopt_array.