Ошибка получения заголовков 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
Я столкнулся с той же проблемой и попробовал все вышеперечисленные решения. К сожалению, ничего не сработало.
- Тайм-аут сокета (не работает)
- Пользовательский агент (не работает)
- Конфигурация 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.