Ошибка получения заголовков http в SoapClient

Я пытаюсь вызвать WS через https на удаленном хосте: удаленный порт, и я получаю:

Ошибка при загрузке заголовков http

использование PHP5 SoapClient; Я могу получить список функций, выполнив $client->__getFunctions(), но когда я вызываю $client->myFunction(...), я всегда получаю эту ошибку.

Я гуглил и обнаружил, что увеличение default_socket_timeout в php.ini должно исправить это, но это не сработало.

Кто-нибудь может предложить мне решение?

ОБНОВЛЕНИЕ: вот код:

$wsdl="myWSDL";

$client = new SoapClient($wsdl,array('connection_timeout'=>5,'trace'=>true,'soap_version'=>SOAP_1_2));

var_dump($client->__getFunctions());

try {
    $response=$client->myFunction("1","2","3");
         } catch (SoapFault $fault) {
    var_dump($fault);
    }
}

всегда заканчивается ошибкой.

Как мне решить проблему?

Ответ 1

Эта ошибка часто наблюдается, когда значение default_socket_timeout превышено для ответа SOAP. (См. ссылку.)

Примечание от конструктора SoapClient: параметр connection_timeout используется для определения значения времени ожидания для подключения к службе, а не для времени ожидания его ответа.

Вы можете увеличить его так:

ini_set('default_socket_timeout', 600); // or whatever new value you want

Это должно сказать вам, является ли тайм-аут проблемой, или у вас есть другая проблема. Имейте в виду, что вы не должны использовать это как постоянное решение, а, скорее, посмотреть, избавится ли он от ошибки, прежде чем приступить к расследованию, почему служба SOAP реагирует так медленно. Если служба постоянно медленная, вам, возможно, придется рассмотреть возможность автономной/пакетной обработки.

Ответ 2

Просто хотел поделиться решением этой проблемы в моей конкретной ситуации (у меня были одинаковые симптомы). В моем сценарии оказалось, что сертификат ssl, предоставляемый веб-службой, больше не доверяет. Фактически это было связано с новым брандмауэром, который был установлен клиентом, который мешал запросу SOAP, но конечным результатом было то, что сертификат не был правильно обслуживан/доверен.

Было трудно отследить, потому что вызов SoapClient (даже с trace = 1) не дает очень полезной обратной связи.

Мне удалось доказать ненадежный сертификат, используя:

openssl s_client -connect <web service host>:<port>

Я знаю, что это не будет ответом на все проблемы, но, надеюсь, это помогает кому-то. В любом случае, я думаю, что важно понять, что причина этой ошибки (ошибка: "HTTP" faultstring: "Ошибка получения заголовков HTTP" ) обычно будет проблемой сети/сокета/протокола/связи, а не просто "недостаточно разрешать времени для запроса". Я не могу себе представить, что расширение значения default_socket_timeout позволит решить эту проблему очень часто, и даже если это произойдет, наверняка было бы лучше решить вопрос о том, почему это так медленно, в первую очередь.

Ответ 3

Я полагаю, что это слишком поздно, но у меня такая же проблема. Я пробую тайм-аут сокета, но он не работает. Моя проблема заключалась в том, что клиент и сервер, на том же физическом сервере. Когда клиентский код работает на одном физическом сервере, я получаю эту ошибку, но с тем же кодом клиента, который перемещается на мой локальный хост, запрашивая сервер (клиент и сервер выполнялись в двух разных метоках) все работает нормально.

Возможно, это может помочь кому-то еще!

Ответ 4

Установка 'keep_alive' на false работала для меня:

new SoapClient($api_url, array('keep_alive' => false));

Ответ 5

Я столкнулся с той же проблемой и попробовал все вышеперечисленные решения. К сожалению, ничего не сработало.

  1. Тайм-аут сокета (не работает)
  2. Пользовательский агент (не работает)
  3. Конфигурация SoapClient, cache_wsdl и Keep-Alive и т.д...

Я решил свою проблему с добавлением свойства заголовка обжатия. Это действительно требуется, когда вы ожидаете ответа в сжатом формате gzip.

//set the Headers of Soap Client. 
$client = new SoapClient($wsdlUrl, array(
    'trace' => true, 
    'keep_alive' => true,
    'connection_timeout' => 5000,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'compression'   => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
));

Надеюсь, это поможет.

Удачи.

Ответ 6

Конфигурация, которая работала для меня, определяла на моем php script следующие параметры:

ini_set('default_socket_timeout', 5000);
$client = new \SoapClient($url,array(
    'trace' =>true,
    'connection_timeout' => 5000,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'keep_alive' => false,
));

Прошу прокомментировать.

Самое важное определение параметра, согласно моему опыту с этой проблемой, было

ini_set('default_socket_timeout', 5000);

Во время моих тестов я определил default_socket_timeout до 5 секунд, и ошибка "Ошибки при получении заголовков http" была поднята мгновенно.

Надеюсь, это поможет вам!

Ответ 7

Я просто хотел добавить, для полноты, что похоже на Manachi, я получил это сообщение, потому что сертификат клиента, который я использовал, требовал кодовую фразу, и у меня случайно был дополнительный символ в конце фразы. Это сообщение просто для того, чтобы предложить еще одно предложение для изучения. Если хост требует использования сертификата клиента (через параметр local_cert), убедитесь, что вы указали правильный путь к сертификату и правильную кодовую фразу (если необходимо). Если вы этого не сделаете, очень вероятно, что вы увидите это же сообщение об ошибке.

Ответ 8

Ни один из вышеперечисленных методов не работал у меня.

Когда я проанализировал заголовок запроса из __getLastRequestHeaders, я увидел следующее:

POST /index.php/api/index/index/?SID=012345 HTTP/1.1 Host: www.XYZ.com

URL API, который я использовал, был другим, например, www.ABC.com. Я изменил URL-адрес API на www.XYZ.com/index.php/api?wsdl, а затем он сработал.

Оба URL-адреса возвратили один и тот же WSDL с одного и того же сервера, но только один разрешенный вход.

Ответ 9

У меня была эта проблема, и я проверил, и в моем случае был брандмауэр. PHP неправильно показывает ошибку. Чтобы выполнить запрос, ответил брандмауэр:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
<html
...
<h1>Direct Access IP is not allowed</h1>
...
</html>

SoapClient ожидает конверт SOAP, но получает код HTML. Именно поэтому PHP отвечает: "Ошибка получения заголовков Http", потому что он не может понять, что он получил в ответ. Чтобы устранить эту проблему, обратитесь к сетевому администратору, чтобы проверить, нет ли какого-либо брандмауэра, NAT или прокси-сервера, а затем попросите их принять необходимые меры.

Ответ 10

Проверьте ответ HTTP-заголовка. В моем случае на API-сайте был установлен следующий заголовок:

<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

Кажется, что PHP SoapClient не может справиться с этой опцией. В результате тело ответа было пустым, но длина содержимого в заголовке ответа была установлена ​​правильно.

Удалите эту строку или измените ее на "закрыть", решив мою проблему.

Ответ 11

У меня была такая же проблема, и я попробовал следующее, отключив keep_alive.

$api_proxy = new SoapClient($api_url, array('trace' => true, 'keep_alive' => false));

Однако это не сработало для меня. То, что работало для меня, было отключением кэша SOAP. Кажется, он кэшировал неправильные запросы, и после отключения я фактически заметил, что мои запросы выполнялись быстрее.

На сервере linux вы можете найти это в своем файле /etc/php.ini.

Найдите soap.wsdl_cache_enabled=1 и измените его на soap.wsdl_cache_enabled=0.

Не забудьте перезагрузить apache. service httpd reload

Ответ 12

Другой возможной причиной этой ошибки могут быть некоторые операции OpenSSL, оставляющие не очищенные ошибки. Поместите этот фрагмент кода перед SOAP-запросом, чтобы очистить их:

while (openssl_error_string()) {}

Ответ 13

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

например. https://soap-request-domain-here.com/path/to/file.wsdl

Ответ 14

Мы встречали Error fetching http headers при каждом втором вызове SoapClient::__soapCall(,). Однако не каждая конечная точка/сервер мыла была затронута.

Оказалось, что переключение на http надежно работает для всех серверов, но соединения через https/безопасный HTTP показали вышеупомянутые симптомы. openssl_error_string(), как предложил Furgas, не вернул никаких ошибок.

Оказалось, что некорректно работающие мыльные серверы отправляют HTTP-заголовок с каждым ответом, что приводит к тому, что мыльный клиент задыхается от второго мыльного вызова: Connection: Upgrade, close. Хорошо работающие серверы не отправили Обновление на последовательные ответы.

Что сработало для нас:

  • установив keep_alive в значение false, как упомянул Тьяго
  • Отключение заголовков Upgrade- и Connection через файлы .htaccess

Хотя мыльные серверы с хорошим поведением не нуждались в этом, однажды для неправильного поведения потребовалось установить для keep_alive значение false и отключить заголовки.

# .htaccess
Header unset Upgrade
Header unset Connection

Основная причина до сих пор неясна, но в Apache имеется отчет об ошибке относительно заголовков обновления при использовании HTTPS.