protected function httpRequest($method, $url, $requestBody = null, $raw = false)
{
$method = strtoupper($method);
// response body and headers
$headers = [];
$headersFinished = false;
$body = '';
$options = [CURLOPT_USERAGENT => 'Yii Framework ' . Yii::getVersion() . ' ' . __CLASS__, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_HTTPHEADER => ['Expect:'], CURLOPT_WRITEFUNCTION => function ($curl, $data) use(&$body) {
$body .= $data;
return mb_strlen($data, '8bit');
}, CURLOPT_HEADERFUNCTION => function ($curl, $data) use(&$headers, &$headersFinished) {
if ($data === '') {
$headersFinished = true;
} elseif ($headersFinished) {
$headersFinished = false;
}
if (!$headersFinished && ($pos = strpos($data, ':')) !== false) {
$headers[strtolower(substr($data, 0, $pos))] = trim(substr($data, $pos + 1));
}
return mb_strlen($data, '8bit');
}, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_FORBID_REUSE => false];
if (!empty($this->auth) || isset($this->nodes[$this->activeNode]['auth']) && $this->nodes[$this->activeNode]['auth'] !== false) {
$auth = isset($this->nodes[$this->activeNode]['auth']) ? $this->nodes[$this->activeNode]['auth'] : $this->auth;
if (empty($auth['username'])) {
throw new InvalidConfigException('Username is required to use authentication');
}
if (empty($auth['password'])) {
throw new InvalidConfigException('Password is required to use authentication');
}
$options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
$options[CURLOPT_USERPWD] = $auth['username'] . ':' . $auth['password'];
}
if ($this->connectionTimeout !== null) {
$options[CURLOPT_CONNECTTIMEOUT] = $this->connectionTimeout;
}
if ($this->dataTimeout !== null) {
$options[CURLOPT_TIMEOUT] = $this->dataTimeout;
}
if ($requestBody !== null) {
$options[CURLOPT_POSTFIELDS] = $requestBody;
}
if ($method == 'HEAD') {
$options[CURLOPT_NOBODY] = true;
unset($options[CURLOPT_WRITEFUNCTION]);
} else {
$options[CURLOPT_NOBODY] = false;
}
if (is_array($url)) {
list($protocol, $host, $q) = $url;
if (strncmp($host, 'inet[', 5) == 0) {
$host = substr($host, 5, -1);
if (($pos = strpos($host, '/')) !== false) {
$host = substr($host, $pos + 1);
}
}
$profile = "{$method} {$q}#{$requestBody}";
$url = "{$protocol}://{$host}/{$q}";
} else {
$profile = false;
}
Yii::trace("Sending request to elasticsearch node: {$method} {$url}\n{$requestBody}", __METHOD__);
if ($profile !== false) {
Yii::beginProfile($profile, __METHOD__);
}
$this->resetCurlHandle();
curl_setopt($this->_curl, CURLOPT_URL, $url);
curl_setopt_array($this->_curl, $options);
if (curl_exec($this->_curl) === false) {
throw new Exception('Elasticsearch request failed: ' . curl_errno($this->_curl) . ' - ' . curl_error($this->_curl), ['requestMethod' => $method, 'requestUrl' => $url, 'requestBody' => $requestBody, 'responseHeaders' => $headers, 'responseBody' => $this->decodeErrorBody($body)]);
}
$responseCode = curl_getinfo($this->_curl, CURLINFO_HTTP_CODE);
if ($profile !== false) {
Yii::endProfile($profile, __METHOD__);
}
if ($responseCode >= 200 && $responseCode < 300) {
if ($method == 'HEAD') {
return true;
} else {
if (isset($headers['content-length']) && ($len = mb_strlen($body, '8bit')) < $headers['content-length']) {
throw new Exception("Incomplete data received from elasticsearch: {$len} < {$headers['content-length']}", ['requestMethod' => $method, 'requestUrl' => $url, 'requestBody' => $requestBody, 'responseCode' => $responseCode, 'responseHeaders' => $headers, 'responseBody' => $body]);
}
if (isset($headers['content-type']) && (!strncmp($headers['content-type'], 'application/json', 16) || !strncmp($headers['content-type'], 'text/plain', 10))) {
return $raw ? $body : Json::decode($body);
}
throw new Exception('Unsupported data received from elasticsearch: ' . $headers['content-type'], ['requestMethod' => $method, 'requestUrl' => $url, 'requestBody' => $requestBody, 'responseCode' => $responseCode, 'responseHeaders' => $headers, 'responseBody' => $this->decodeErrorBody($body)]);
}
} elseif ($responseCode == 404) {
return false;
} else {
throw new Exception("Elasticsearch request failed with code {$responseCode}.", ['requestMethod' => $method, 'requestUrl' => $url, 'requestBody' => $requestBody, 'responseCode' => $responseCode, 'responseHeaders' => $headers, 'responseBody' => $this->decodeErrorBody($body)]);
}
}