Таймаут чтения в классе Core_Http с драйвером сокетов

Для реализации местоположения пользователя на сайте под управлением HostCMS мы обычно используем класс Core_Geoip, который для определения города обращается к сервису ipgeobase.ru. В начале января этот сервис был недоступен или перегружен, и у клиента наблюдалась проблема с зависанием сайта, которое было вызвано как раз обращением к этому сервису. В таком поведении была некоторая странность, ведь внутри класса на выполнение запроса устанавливается таймаут запроса, который в случае долгого ответа/неответа должен прерывать запрос, но похоже, что он не сработал, почему же?

В классе Core_Geoip есть такой код, устанавливающий таймаут запроса в 5 секунд:

$oCore_Http = Core_Http::instance()
	->url($sUrl)
	->port($iPort)
	->method('GET')
	->timeout(5)
	->execute();

В качестве драйвера для HTTP-запросов на сайте используется реализация на сокетах через класс Core_Http_Socket, идем внутрь него, внимательно смотрим на код и видим, что внутри устанаваливается таймаут создания сокета:

$fp = @fsockopen($socketHost, $this->_port, $errno, $errstr, $this->_timeout);

...и таймаут потока:

if (function_exists('stream_set_timeout'))
{
	stream_set_timeout($fp, $this->_timeout);
}

Далее идем в документацию функций stream_set_timeout и fgets и читаем, что для определения таймаута потока необходимо анализировать возвращаемый результат либо stream_get_meta_data, либо fgets, чего не в коде драйвера Core_Http_Socket не выполняется:

$datastr = '';

while (!feof($fp))
{
	$datastr .= fgets($fp, 65536);
}

fclose($fp);

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

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

comments powered by Disqus


К списку Предыдущий "2 типа оплаты задач"