@rolecs

Как сделать curl PUT-запрос к API метрики на изменение счетчика (PHP)?

Этот curl запрос в терминале работает, добавляет зеркала:
curl -X PUT https://api-metrika.yandex.net/management/v1/counter/COUNTER_VAR -H "Host: api-metrika.yandex.net" -H "Authorization: OAuth TOKEN_VAR" -H "Content-Type: application/x-yametrika+json" -d '{"counter":{"mirrors2":[{"site":"test.example.com"},{"site":"test2.example.com"},{"site":"test3.example.com"},{"site":"test4.example.com"},{"site":"test5.example.com"}]}}'

Этот на PHP не работает:
$url = "https://api-metrika.yandex.net/management/v1/counter/$COUNTER_VAR";
$headers = [
   "Host: api-metrika.yandex.net",
   "Authorization: OAuth $TOKEN_VAR",
   "Content-Type: application/x-yametrika+json",
];
$data = '{"counter":{"mirrors2":[{"site":"test.example.com"},{"site":"test2.example.com"},{"site":"test3.example.com"},{"site":"test4.example.com"},{"site":"test5.example.com"}]}}';

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

//for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

$resp = curl_exec($curl);
curl_close($curl);
var_dump($resp);

Отдает почти моментально на одном сервере: bool (false)

На другом сервере через 30 секунд отдает: string(389) "{"errors":[{"error_type":"invalid_json","message":"I/O error while reading input message; nested exception is java.io.IOException: java.util.concurrent.TimeoutException: Idle timeout expired: 30000/30000 ms"}],"code":400,"message":"I/O error while reading input message; nested exception is java.io.IOException: java.util.concurrent.TimeoutException: Idle timeout expired: 30000/30000 ms"}"
  • Вопрос задан
  • 208 просмотров
Решения вопроса 1
@rolecs Автор вопроса
Верную правку предложил pantsarny, проблема была в опции:
curl_setopt($curl, CURLOPT_PUT, true);
Работающая опция:
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
Работающий код:
$COUNTER_VAR = '';
$TOKEN_VAR = '';
$url = "https://api-metrika.yandex.net/management/v1/counter/$COUNTER_VAR";
// $data = '{"counter":{"mirrors2":[{"site":"test.example.com"},{"site":"test2.example.com"},{"site":"test3.example.com"},{"site":"test4.example.com"},{"site":"test5.example.com"}]}}'; // так тоже работает
$data = [
    'counter' => [
        'mirrors2' => [
            ['site' => 'test.example.com'],
            ['site' => 'test2.example.com'],
            ['site' => 'test3.example.com'],
            ['site' => 'test4.example.com'],
            ['site' => 'test5.example.com'],
        ],
    ],
];
$data = json_encode($data);
$headers = array(
   //"Host: api-metrika.yandex.net", // оказалось необязательно
   "Authorization: OAuth $TOKEN_VAR",
   "Content-Type: application/x-yametrika+json",
   //"Content-Length: " . strlen($data), // оказалось необязательно
);
$curl = curl_init($url);
// curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // раскомментировать в случае ошибки "HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)"
curl_setopt($curl, CURLOPT_URL, $url);
// curl_setopt($curl, CURLOPT_PUT, true); // неработающая опция
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); // работающая опция
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

//for debug only!
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // если будет ругаться на сертификат раскомментировать
//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // если будет ругаться на сертификат раскомментировать

$resp = curl_exec($curl);

if ($resp === false) {
    echo curl_error($curl);
} else {
    var_dump($resp);
}

curl_close($curl);
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
++$data = '{"counter":{"mirrors2":[{"site":"test.example.com"},{"site":"test2.example.com"},{"site":"test3.example.com"},{"site":"test4.example.com"},{"site":"test5.example.com"}]}}';
$headers = [
    "Host: api-metrika.yandex.net",
    "Authorization: OAuth $TOKEN_VAR",
    "Content-Type: application/x-yametrika+json",
++  "Content-Length: " . strlen($data),
];
--$data = '{"counter":{"mirrors2":[{"site":"test.example.com"},{"site":"test2.example.com"},{"site":"test3.example.com"},{"site":"test4.example.com"},{"site":"test5.example.com"}]}}';
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы