public function doRequest($context, $method, $host, $path, $params, $data, $connectTimeout, $readTimeout)
{
if (strpos($host, "http") === 0) {
$url = $host . $path;
} else {
$url = "https://" . $host . $path;
}
if ($params != null && count($params) > 0) {
$params2 = array();
foreach ($params as $key => $val) {
if (is_array($val)) {
$params2[$key] = json_encode($val);
} else {
$params2[$key] = $val;
}
}
$url .= "?" . http_build_query($params2);
}
// initialize curl library
$curlHandle = curl_init();
//curl_setopt($curlHandle, CURLOPT_VERBOSE, true);
if ($context->adminAPIKey == null) {
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array_merge(array('X-Algolia-Application-Id: ' . $context->applicationID, 'X-Algolia-API-Key: ' . $context->apiKey, 'Content-type: application/json'), $context->headers));
} else {
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array_merge(array('X-Algolia-Application-Id: ' . $context->applicationID, 'X-Algolia-API-Key: ' . $context->adminAPIKey, 'X-Forwarded-For: ' . $context->endUserIP, 'X-Forwarded-API-Key: ' . $context->rateLimitAPIKey, 'Content-type: application/json'), $context->headers));
}
curl_setopt($curlHandle, CURLOPT_USERAGENT, "Algolia for PHP " . Version::get());
//Return the output instead of printing it
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curlHandle, CURLOPT_FAILONERROR, true);
curl_setopt($curlHandle, CURLOPT_ENCODING, '');
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curlHandle, CURLOPT_CAINFO, $this->cainfoPath);
curl_setopt($curlHandle, CURLOPT_URL, $url);
$version = curl_version();
if (version_compare(phpversion(), '5.2.3', '>=') && version_compare($version['version'], '7.16.2', '>=') && $connectTimeout < 1) {
curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT_MS, $connectTimeout * 1000);
curl_setopt($curlHandle, CURLOPT_TIMEOUT_MS, $readTimeout * 1000);
} else {
curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, $connectTimeout);
curl_setopt($curlHandle, CURLOPT_TIMEOUT, $readTimeout);
}
curl_setopt($curlHandle, CURLOPT_NOSIGNAL, 1);
# The problem is that on (Li|U)nix, when libcurl uses the standard name resolver, a SIGALRM is raised during name resolution which libcurl thinks is the timeout alarm.
curl_setopt($curlHandle, CURLOPT_FAILONERROR, false);
if ($method === 'GET') {
curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curlHandle, CURLOPT_HTTPGET, true);
curl_setopt($curlHandle, CURLOPT_POST, false);
} else {
if ($method === 'POST') {
$body = $data ? json_encode($data) : '';
curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curlHandle, CURLOPT_POST, true);
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $body);
} elseif ($method === 'DELETE') {
curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($curlHandle, CURLOPT_POST, false);
} elseif ($method === 'PUT') {
$body = $data ? json_encode($data) : '';
curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $body);
curl_setopt($curlHandle, CURLOPT_POST, true);
}
}
$mhandle = $context->getMHandle($curlHandle);
// Do all the processing.
$running = null;
do {
$mrc = curl_multi_exec($mhandle, $running);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($running && $mrc == CURLM_OK) {
if (curl_multi_select($mhandle, 0.1) == -1) {
usleep(100);
}
do {
$mrc = curl_multi_exec($mhandle, $running);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
$http_status = (int) curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);
$response = curl_multi_getcontent($curlHandle);
$error = curl_error($curlHandle);
if (!empty($error)) {
throw new \Exception($error);
}
if ($http_status === 0 || $http_status === 503) {
// Could not reach host or service unavailable, try with another one if we have it
$context->releaseMHandle($curlHandle);
curl_close($curlHandle);
return null;
}
$answer = json_decode($response, true);
$context->releaseMHandle($curlHandle);
curl_close($curlHandle);
if (intval($http_status / 100) == 4) {
throw new AlgoliaException(isset($answer['message']) ? $answer['message'] : $http_status + " error");
} elseif (intval($http_status / 100) != 2) {
throw new \Exception($http_status . ": " . $response);
}
switch (json_last_error()) {
case JSON_ERROR_DEPTH:
$errorMsg = 'JSON parsing error: maximum stack depth exceeded';
break;
case JSON_ERROR_CTRL_CHAR:
$errorMsg = 'JSON parsing error: unexpected control character found';
break;
case JSON_ERROR_SYNTAX:
$errorMsg = 'JSON parsing error: syntax error, malformed JSON';
break;
case JSON_ERROR_STATE_MISMATCH:
$errorMsg = 'JSON parsing error: underflow or the modes mismatch';
break;
case defined('JSON_ERROR_UTF8') ? JSON_ERROR_UTF8 : -1:
// PHP 5.3 less than 1.2.2 (Ubuntu 10.04 LTS)
$errorMsg = 'JSON parsing error: malformed UTF-8 characters, possibly incorrectly encoded';
break;
case JSON_ERROR_NONE:
default:
$errorMsg = null;
break;
}
if ($errorMsg !== null) {
throw new AlgoliaException($errorMsg);
}
return $answer;
}