Ошибка получения заголовков 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);
    }
}

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

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


person Cris    schedule 22.02.2012    source источник
comment
Хм... ini_set('user_agent','somerandomuseragent'); помогает? Вы пробовали вручную запросить этот сервис?   -  person Wrikken    schedule 23.02.2012
comment
Если я делаю ручной запрос к WS через Lynx или curl, он работает нормально; пытались установить user_agent, но безуспешно   -  person Cris    schedule 23.02.2012
comment
Это сообщение об ошибке часто появляется после default_socket_timeout. Можно ли увеличить его значение с помощью ini_set?   -  person cmbuckley    schedule 23.02.2012
comment
@Cris Привет, Крис, ты решил эту проблему? У меня тоже такая же проблема, и мне нужно исправить проблему :)   -  person Webster    schedule 22.02.2016


Ответы (15)


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

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

Вы можете увеличить его следующим образом:

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

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

person cmbuckley    schedule 22.02.2012
comment
Я пытался увеличить его до 600, но всегда получаю [faultstring]=> string(27) Error Fetching http headers - person Cris; 23.02.2012
comment
Хорошо, затем повторите предложение Wrikken выше, за исключением того, что это не ini_set, а другой параметр в вашем массиве, переданный конструктору. Я предполагаю, что он предложил это на основе PHP #37054, и ваша ошибка может быть похожим. Попробуйте выполнить запрос вручную, используя curl и -H "User-Agent:", и посмотрите, получите ли вы заголовок Location в ответе. - person cmbuckley; 23.02.2012
comment
Спасибо за внимание; я пробовал, как вы предложили, но безуспешно; когда я делаю curl, я вижу ‹soap:operation soapAction= style=rpc/› ... это может помочь? - person Cris; 23.02.2012
comment
Было бы полезно, если бы вы могли предоставить больше информации (например, полный вывод вашего вызова curl с -v, чтобы увидеть заголовки запроса/ответа). - person cmbuckley; 23.02.2012
comment
Честно говоря, бывает ли когда-нибудь ситуация, когда вы хотите, чтобы пользователь сидел и ждал 600 секунд ответа? Пока я нашел 3 сообщения stackoverflow с этим вопросом, и люди продолжают предлагать «увеличить ограничение по времени». Неудивительно, что ответы не принимаются. Я еще не решил проблему, но подозреваю, что это проблема, связанная с сетью/сокетом, которая обычно вызывает это. - person Manachi; 22.01.2013
comment
Честно говоря, это не лучший ответ - 600 секунд были просто глупо большим числом, к которому я пришел, добавив лишний ноль :-) Честно говоря, я имел в виду это только как испытание, чтобы увидеть, предотвратит ли это ошибку, то есть вы может оценить фактическое время отклика. Но если это действительно проблема, и ответ занимает больше 60 секунд, то я думаю, что решение проблемы времени отклика было бы более уместным! - person cmbuckley; 25.06.2013
comment
У меня была такая же проблема, я использовал это решение, и оно у меня тоже не работает. - person Davide Vernizzi; 26.06.2013
comment
Это сработало для меня. Я получил ответ, если записей меньше, если ответ огромен, то он зависает. Так что, очевидно, происходит тайм-аут, и это помогло. Спасибо @cmbuckley - person Kalyan Chakravarthi V; 06.08.2019

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

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

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

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

Я знаю, что это не будет решением проблемы для всех, но, надеюсь, кому-то это поможет. В любом случае, я думаю, важно понимать, что причиной этой ошибки (код ошибки: «HTTP», строка ошибки: «Ошибка получения заголовков http») обычно является проблема с сетью/сокетом/протоколом/связью, а не просто «недостаточно время запроса». Я не могу представить, что расширение значения default_socket_timeout будет решать эту проблему очень часто, и даже если это произойдет, конечно, было бы лучше сначала решить вопрос, ПОЧЕМУ он такой медленный.

person Manachi    schedule 23.01.2013

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

Может быть, это может помочь кому-то еще!

person Jonathan Huet    schedule 25.07.2013
comment
Это может быть связано либо с тем, что имя хоста разрешается в ваш общедоступный IP-адрес, а маршрутизатор не знает, как правильно его обработать (просто добавьте ваше имя хоста в файл hosts и укажите его на 127.0.0.1), либо с тем, что общедоступный и частный порты сервера могут будь другим. - person toster-cx; 30.08.2018

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

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

Я решил свою проблему, добавив свойство заголовка compression. На самом деле это необходимо, когда вы ожидаете ответа в сжатом формате 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,
));

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

Удачи.

person Sanjay Mohnani    schedule 26.05.2018
comment
Потрясающий! Мне помог параметр сжатия! - person l00k; 30.08.2018
comment
'user_agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0', уменьшит время отклика на 100%. - person Ahmed Aboud; 29.03.2021

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

new SoapClient($api_url, array('keep_alive' => false));
person Thiago Sathler    schedule 19.06.2018

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

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» возникла мгновенно.

Я надеюсь, что это поможет вам!

person Marcelo Tonon Chiovatto    schedule 30.11.2017

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

person borq    schedule 06.11.2013

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

Когда я проанализировал заголовок запроса из __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 с одного и того же сервера, но разрешен только один вход в систему.

person humbads    schedule 27.02.2016

У меня была эта проблема, и я проверил, и в моем случае это был брандмауэр. 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 или прокси-сервер, а затем попросите их принять необходимые меры.

person Mauro    schedule 04.02.2014
comment
Примечание: в SoapClient булевы параметры, не знаю почему, работают только с передачей 0 и 1. Пример: array ( ... 'trace' => 1, 'exceptions' => 0, ... ); - person Mauro; 05.02.2014

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

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

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

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

person Matthias Kleine    schedule 24.08.2015

У меня была такая же проблема, и я попробовал следующее, отключив 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.

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

person MagentoMan    schedule 16.12.2016

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

while (openssl_error_string()) {}
person Furgas    schedule 18.10.2018

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

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

person John Langford    schedule 10.07.2019

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

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

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

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

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

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

# .htaccess
Header unset Upgrade
Header unset Connection

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

person Richard Kiefer    schedule 08.08.2019

В последних выпусках Zend SOAP клиент вообще не имеет параметров «connection_timeout» и «Keep_alive».

введите здесь описание изображения

Вы можете увидеть фрагмент кода, который я приложил в виде изображения. Единственный способ решить эту проблему — увеличить время ожидания сокета по умолчанию в php.ini.

default_socket_timeout = 1000

Я надеюсь, что это решит вашу проблему. Дайте голос, если это работает.

person sivaprakash    schedule 14.01.2020