Ошибка PHP cURL: пустой ответ с сервера

У меня есть функция класса для взаимодействия с RESTful API для Last.FM — ее цель — получить самые последние треки для мой пользователь. Вот:

private static $base_url = 'http://ws.audioscrobbler.com/2.0/';

public static function getTopTracks($options = array())
{
  $options = array_merge(array(
    'user' => 'bachya',
    'period' => NULL,
    'api_key' => 'xxxxx...', // obfuscated, obviously
  ), $options);

  $options['method'] = 'user.getTopTracks';

  // Initialize cURL request and set parameters
  $ch = curl_init();
  curl_setopt_array($ch, array(
    CURLOPT_URL            => self::$base_url,
    CURLOPT_POST           => TRUE,
    CURLOPT_POSTFIELDS     => $options,
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
  ));

  $results = curl_exec($ch);
  return $results;
}

Это возвращает "Empty reply from server". Я знаю, что некоторые предполагают, что эта ошибка происходит из-за какой-то неисправности в сетевой инфраструктуре; Я не верю, что это верно в моем случае. Если я запускаю запрос cURL через командную строку, я получаю свои данные; сервис Last.FM запущен и доступен.

Прежде чем я пойду к этим людям и узнаю, не изменилось ли что-нибудь, я хотел бы проконсультироваться с вами, замечательные люди, и посмотреть, есть ли какая-то проблема в моем коде, которая может вызвать это.

Спасибо!

ОТВЕТ: @Jan Kuboschek помог мне наткнуться на то, что (возможно) здесь происходит. Предоставляя CURLOPT_POSTFIELDS ассоциативный массив, указывается конкретный тип контента, который может не работать с некоторыми службами RESTful. Более разумное решение — вручную создать версию этих данных в кодировке URL и передать ее как файл CURLOPT_POSTFIELDS.

Для получения дополнительной информации посетите: http://www.brandonchecketts.com/archives/array-versus-string-in-curlopt_postfields


person ABach    schedule 10.06.2010    source источник


Ответы (5)


Распространенной проблемой являются пробелы в URL-адресе — в начале, в середине или в конце. Вы это проверяли?

Редактировать. Согласно комментариям ниже, расстояние не является проблемой.

Я запустил ваш код и столкнулся с той же проблемой - никакого вывода. Я попробовал URL-адрес, и с запросом GET сервер разговаривает со мной. Я бы сделал следующее:

  1. В качестве $base_url используйте следующее: $base_url = 'http://ws.audioscrobbler.com/2.0/?user=bachya&period=&api_key=xxx&method=user.getTopTracks';

  2. Удалите поля сообщения из вашего запроса.

Изменить Я удалил ваш код из класса, так как у меня не было остального, и изменил его. Следующий код работает идеально для меня. Если эти изменения не работают для вас, я полагаю, что ваша ошибка связана с другой функцией.

<?php


function getTopTracks()
{
  $base_url = 'http://ws.audioscrobbler.com/2.0/?user=bachya&period=&api_key=8066d2ebfbf1e1a8d1c32c84cf65c91c&method=user.getTopTracks';
  $options = array_merge(array(
    'user' => 'bachya',
    'period' => NULL,
    'api_key' => 'xxxxx...', // obfuscated, obviously
  ));

  $options['method'] = 'user.getTopTracks';

  // Initialize cURL request and set parameters
  $ch = curl_init($base_url);
  curl_setopt_array($ch, array(
    CURLOPT_URL            => $base_url,
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
  ));

  $results = curl_exec($ch);
  return $results;
}

echo getTopTracks();

?>
person Jan K.    schedule 10.06.2010
comment
К сожалению, это не проблема — я обновил свой исходный пост, чтобы показать URL-адрес ($ base_url), который я использую. Спасибо хоть. :-\ - person ABach; 11.06.2010
comment
Обновил мой ответ. Дайте мне знать, если это все еще не работает. Я не мог продолжать тестирование, так как сервер сказал мне, что мне нужен действительный ключ API. - person Jan K.; 11.06.2010
comment
Ладно, пробовал - вроде висит (работает) чуть дольше. Я var выгружаю результаты curl_exec и получаю взамен false... Я бы предпочел не указывать свой ключ API, но их достаточно легко получить. - person ABach; 11.06.2010
comment
Хорошо, это беспокоит меня сейчас. Как получить ключ API? - person Jan K.; 11.06.2010
comment
Проверьте здесь: last.fm/api/account - спасибо за то, что нас так же беспокоят! :) - person ABach; 11.06.2010
comment
Хорошо, вы наткнулись на то, что я обновил в своем исходном посте. Спасибо за помощь! :) - person ABach; 11.06.2010
comment
У меня была та же проблема. Infact space создает проблемы с запросом на завивание. У меня был keyowrd = iphone 5 в моем URL-адресе, и я всегда получал пустой ответ. Когда я заменил keyowrd = iphone + 5, он работал нормально :) - person casper123; 12.04.2014

Сервер получил ваш запрос, но отправил пустой ответ. Проверьте результат curl_getinfo($ch, CURLINFO_HTTP_CODE), чтобы узнать, ответил ли сервер с кодом ошибки HTTP.

Обновление: Хорошо, поэтому сервер отвечает кодом состояния HTTP 100 Continue. В этом случае это должно решить вашу проблему:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

Я нашел это здесь: PHP и cURL: отключение заголовка 100-continue. Надеюсь, что это работает!

person cygri    schedule 10.06.2010
comment
Вар-дампинг возвращает 100 - надеюсь, полезно? - person ABach; 11.06.2010
comment
Еще одно обновление: в приведенном выше решении Яна используется GET вместо POST, и, как отметил Михал, это на самом деле лучше для чтения вызовов API. Материал 100 Continue не применяется к GET, поэтому он аккуратно избегает реальной проблемы. Если вы также хотите получить доступ к службам записи, вам следует использовать POST для этих вызовов и попробовать мой ответ. - person cygri; 11.06.2010

Я столкнулся с той же проблемой. Мой Http_code вернул 200, но мой ответ был пуст. Там может быть много причин для этого, как я испытал.

--Ваши хедеры могут быть неверными

CURLOPT_HTTPHEADER => array('Content-Type:application/json', 'Expect:')

--Возможно, вам потребуется отправить данные в виде полей сообщения в culr, а не прикреплять их к URL-адресу, например url?p1=a1&p2=a2.

$data = array (p1=>a1, p2=>a2)
CURLOPT_POSTFIELDS => $data

Таким образом, ваш массив параметров будет похож на приведенный ниже

array(
    CURLOPT_URL => $url,
    CURLOPT_FAILONERROR => TRUE, // FALSE if in debug mode
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_TIMEOUT => 4,
    CURLOPT_HTTPHEADER => array('Content-Type:application/json', 'Expect:'),
    CURLOPT_POST => TRUE,
    CURLOPT_POSTFIELDS => $data,
);
person nmeegama    schedule 21.08.2013

Согласно Last.FM документация API, вы должны использовать метод GET вместо POST для передачи параметров. Когда я изменил POST на GET, я получил ответ о неправильном ключе.

person Michał Pipa    schedule 10.06.2010
comment
Я не вижу в этом документе ничего, что указывало бы на обязательное использование запроса GET при передаче параметров. Не могли бы вы показать мне, где? - person ABach; 11.06.2010
comment
Вообще говоря, вы отправляете параметр метода, выраженный как «package.method», вместе с конкретными аргументами метода на корневой URL-адрес. Например: ws.audioscrobbler.com/2.0/... Если вы обращаетесь к службе записи, вам нужно будет отправить запрос в виде запроса HTTP POST. - person Michał Pipa; 11.06.2010

А вот код для получения информации об альбоме от Laft.FM, даже если возвращается ошибка:

Функция:

function getAlbum($xml,$artist,$album)
{
  $base_url = $xml;
  $options = array_merge(array(
    'user' => 'YOUR_USERNAME',
    'artist'=>$artist,
    'album'=>$album,
    'period' => NULL,
    'api_key' => 'xYxOxUxRxxAxPxIxxKxExYxx', 
  ));

  $options['method'] = 'album.getinfo';

  // Initialize cURL request and set parameters
  $ch = curl_init($base_url);
  curl_setopt_array($ch, array(
    CURLOPT_URL            => 'http://ws.audioscrobbler.com/2.0/',
    CURLOPT_POST           => TRUE,
    CURLOPT_POSTFIELDS     => $options,
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER        => array( 'Expect:' ) ,
    CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
  ));

  $results = curl_exec($ch);
  unset ($options);
  return $results;
}

Использование:

// Get the XML
$xml_error = getAlbum($xml,$artist,$album);

// Show XML error
if (preg_match("/error/i", $xml_error)) {
    echo " <strong>ERRO:</strong> ".trim(strip_tags($xml_error));
}
person Fabiano Shark    schedule 05.05.2011