protected function executeRequest($url, array $additionalParameters = array())
{
$retryableErrorCodes = array(CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, CURLE_READ_ERROR, CURLE_OPERATION_TIMEOUTED, CURLE_HTTP_POST_ERROR, CURLE_SSL_CONNECT_ERROR);
$curlOptions = array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, CURLINFO_HEADER_OUT => true, CURLOPT_VERBOSE => true, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 5, CURLOPT_USERAGENT => strtolower(__CLASS__ . '-PHP-SDK/v' . self::VERSION), CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($additionalParameters), CURLOPT_URL => $url);
if (is_array($this->customCurlOptions)) {
foreach ($this->customCurlOptions as $customCurlOptionKey => $customCurlOptionValue) {
$curlOptions[$customCurlOptionKey] = $customCurlOptionValue;
}
}
$this->rawRequest = $curlOptions;
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$curlResult = false;
$retriesCnt = $this->retriesToConnectCount;
while ($retriesCnt--) {
$this->log->debug(sprintf('try [%s] to connect to host [%s]', $retriesCnt, $this->getDomain()));
$curlResult = curl_exec($curl);
// handling network I/O errors
if (false === $curlResult) {
$curlErrorNumber = curl_errno($curl);
$errorMsg = sprintf('in try[%s] cURL error (code %s): %s' . PHP_EOL, $retriesCnt, $curlErrorNumber, curl_error($curl));
if (false === in_array($curlErrorNumber, $retryableErrorCodes, true) || !$retriesCnt) {
$this->log->error($errorMsg, $this->getErrorContext());
curl_close($curl);
throw new Bitrix24IoException($errorMsg);
} else {
$this->log->warning($errorMsg, $this->getErrorContext());
}
usleep($this->getRetriesToConnectTimeout());
continue;
}
$this->requestInfo = curl_getinfo($curl);
$this->rawResponse = $curlResult;
$this->log->debug('cURL request info', array($this->getRequestInfo()));
curl_close($curl);
break;
}
// handling URI level resource errors
switch ($this->requestInfo['http_code']) {
case 403:
$errorMsg = sprintf('portal [%s] deleted, query aborted', $this->getDomain());
$this->log->error($errorMsg, $this->getErrorContext());
throw new Bitrix24PortalDeletedException($errorMsg);
break;
case 502:
$errorMsg = sprintf('bad gateway to portal [%s]', $this->getDomain());
$this->log->error($errorMsg, $this->getErrorContext());
throw new Bitrix24BadGatewayException($errorMsg);
break;
}
// handling server-side API errors: empty response from bitrix24 portal
if ($curlResult === '') {
$errorMsg = sprintf('empty response from portal [%s]', $this->getDomain());
$this->log->error($errorMsg, $this->getErrorContext());
throw new Bitrix24EmptyResponseException($errorMsg);
}
// handling json_decode errors
$jsonResult = json_decode($curlResult, true);
unset($curlResult);
$jsonErrorCode = json_last_error();
if (null === $jsonResult && JSON_ERROR_NONE !== $jsonErrorCode) {
/**
* @todo add function json_last_error_msg()
*/
$errorMsg = 'fatal error in function json_decode.' . PHP_EOL . 'Error code: ' . $jsonErrorCode . PHP_EOL;
$this->log->error($errorMsg, $this->getErrorContext());
throw new Bitrix24Exception($errorMsg);
}
return $jsonResult;
}