Как мне создать простой обработчик PHP API?
Я написал базовый скрипт API на PHP с использованием CURL - и успешно использовал его версию на другом API, этот специально предназначен для управления DNS-доменами в DigitalOcean - и я не могу отправлять данные?
Прелюдия...
Я понимаю, что доступна библиотека PHP, мне не нужно что-то полнофункциональное или раздутое зависимостями - просто что-то небольшое для локального использования и в первую очередь для того, чтобы помочь мне понять, как RESTful API работает немного лучше в практика - учебное упражнение
Код-нарушитель...
function basic_api_handle($key, $method, $URI, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '.$key,
'Content-Type: application/json')
);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_URL, $URI);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = curl_exec($ch);
if($result === false) error_log("API ERROR: Connection failure: $URI", 0);
curl_close($ch);
return json_decode($result, true);
}
var_dump(basic_api_handle($api_key, 'POST', 'https://api.digitalocean.com/v2/domains', array('name' => 'my-domain.tld', 'ip_address' => '1.2.3.4')));
Это работает с запросом GET, таким как перечисление доменов в учетной записи, но, похоже, не удается опубликовать/отправить данные... это приводит к "необработанной сущности" и "Имя не может быть пустым" - поскольку имя не является пустым и правильно отформатировано (насколько я могу судить), это наводит меня на мысль, что данные отправляются неправильно?
Попытки решения до сих пор...
Я пробовал кодировать данные в формате json (видно в коде), не кодировка json, кодировка URL с кодировкой json и без нее и различные другие варианты без успеха.
Я видел несколько сообщений в Интернете об этой точно такой же проблеме, в частности, с API DigitalOcean (и другим), но ни у кого не было объяснения (кроме как отказаться и использовать библиотеку или что-то в этом роде).
Использование cURL непосредственно с терминала работает и т. Д., Поэтому в API для создания домена нет ничего плохого.
Насколько я поймите, аутентификация работает, и общая настройка работает, так как я могу перечислять домены в учетной записи, я просто не могу ПУБЛИКОВАТЬ или РАЗМЕЩАТЬ новые данные. Я просмотрел документацию API и не могу понять, что я делаю неправильно, может быть, какая-то неправильная кодировка?
Любая помощь будет очень признательна!:)
Редактировать: После большой работы и исследований даже другие простые обработчики API не работают с Цифровым океаном (такие как https://github.com/ledfusion/php-rest-curl ) - есть ли что-то, что нужно этому API в частности, или я упускаю что-то фундаментальное в API в целом?
5 answers
Это может быть перенаправление http 307 или 308.
Может быть"https://api.digitalocean.com/v2/domains "перенаправляет на другой URL-адрес.
Если это так, попробуйте добавить:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
Чтобы заставить curl следовать перенаправлению и сохранить параметры. Рекомендуется также использовать:
curl_setopt($curl, CURLOPT_POSTREDIR, 3);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
Чтобы сохранить тело запроса. Надеюсь, это поможет.
Добавьте заголовок Content-Length
и используйте опцию CURLOPT_POST
для запросов POST
function basic_api_handle($key, $method, $URI, $data) {
$json = json_encode($data)
$headers = array(
'Authorization: Bearer '.$key,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $URI);
if ( $method === 'POST' ) {
curl_setopt($curl, CURLOPT_POST, 1);
} else {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
array_push($headers, 'Content-Length: ' . strlen($json) );
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers)
curl_setopt($ch, CURLOPT_POSTFIELDS, $json );
$result = curl_exec($ch);
if($result === false) error_log("API ERROR: Connection failure: $URI", 0);
curl_close($ch);
return json_decode($result, true);
}
Может быть, это сработает для вас:
function basic_api_handle($key, $method, $URI, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); // <-- Should be set to "GET" or "POST"
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // <-- Maybe the SSL is the problem
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"); // <-- I am not familiar with this API, but maybe it needs a user agent?
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '.$key,
'Content-Type: application/json')
);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_URL, $URI);
curl_setopt($ch, CURLOPT_POST, count($data)); // <-- Add this line which counts the inputs you send
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = curl_exec($ch);
if($result === false) error_log("API ERROR: Connection failure: $URI", 0);
curl_close($ch);
return json_decode($result, true);
}
Это также может быть проблемой заголовка, который вы должны отправить, и вы его пропустили.
Технически это не исправление, а обходной путь. Спасибо всем за ваши комментарии и идеи, к сожалению, ничего не сработало/исправил код, и срок действия награды истек :(
Хотя я понятия не имею, почему опция PHP cURL не сработала (HTTP работает, просто ошибки цифрового океана по неизвестной причине, связанные с проверкой данных post)...
У меня есть новый метод, который НАКОНЕЦ-то РАБОТАЕТ ... (благодаря сообщению jtittle на цифровом Форум океанского сообщества)
Просто уберите эту ссылку в будущем... он является рабочей функцией, использующей потоки и file_get_contents и , а не curl...
<?php
function doapi( $key, $method, $uri, array $data = [] )
{
/**
* DigitalOcean API URI
*/
$api = 'https://api.digitalocean.com/v2';
/**
* Merge DigitalOcean API URI and Endpoint URI
*
* i.e if $uri is set to 'domains', then $api ends up as
* $api = 'https://api.digitalocean.com/v2/domains'
*/
$uri = $api . DIRECTORY_SEPARATOR . $uri;
/**
* Define Authorization and Content-Type Header.
*/
$headers = "Authorization: Bearer $key \r\n" .
"Content-Type: application/json";
/**
* If $data array is not empty, assume we're passing data, so we'll encode
* it and pass it to 'content'. If $data is empty, assume we're not passing
* data, so we won't sent 'content'.
*/
if ( ! empty( $data ) )
{
$data = [
'http' => [
'method' => strtoupper( $method ),
'header' => $headers,
'content' => json_encode( $data )
]
];
}
else
{
$data = [
'http' => [
'method' => strtoupper( $method ),
'header' => $headers
]
];
}
/**
* Create Stream Context
* http://php.net/manual/en/function.stream-context-create.php
*/
$context = stream_context_create( $data );
/**
* Send Request and Store to $response.
*/
$response = file_get_contents( $uri, false, $context );
/**
* Return as decoded JSON (i.e. an array)
*/
return json_decode( $response, true );
}
/**
* Example Usage
*/
var_dump(doapi(
'do-api-key',
'get',
'domains'
));
Я использовал это, чтобы на самом деле успешно опубликовать данные...
var_dump(doapi(
$api_key,
'post',
'domains',
array("name" => (string) $newDomain, "ip_address" => "1.2.3.4")
));
Вы также можете попробовать использовать CURLOPT_POST