/lib/transport/ElasticSearchTransportHTTP.php

https://github.com/ibotty/elasticsearch · PHP · 246 lines · 158 code · 19 blank · 69 comment · 13 complexity · d981bbe03f2133260001d6f7f7e4b919 MD5 · raw file

  1. <?php // vim:set ts=4 sw=4 et:
  2. require_once 'ElasticSearchTransportHTTPException.php';
  3. if (!defined('CURLE_OPERATION_TIMEDOUT'))
  4. define('CURLE_OPERATION_TIMEDOUT', 28);
  5. class ElasticSearchTransportHTTP extends ElasticSearchTransport {
  6. /**
  7. * How long before timing out CURL call
  8. */
  9. const TIMEOUT = 5;
  10. /**
  11. * curl handler which is needed for reusing existing http connection to the server
  12. * @var resource
  13. */
  14. protected $ch;
  15. public function __construct($host='localhost', $port=9200) {
  16. parent::__construct($host, $port);
  17. $this->ch = curl_init();
  18. }
  19. /**
  20. * Index a new document or update it if existing
  21. *
  22. * @return array
  23. * @param array $document
  24. * @param mixed $id Optional
  25. */
  26. public function index($document, $id=false, array $options = array()) {
  27. $url = $this->buildUrl(array($this->type, $id), $options);
  28. $method = ($id == false) ? "POST" : "PUT";
  29. try {
  30. $response = $this->call($url, $method, $document);
  31. }
  32. catch (Exception $e) {
  33. throw $e;
  34. }
  35. return $response;
  36. }
  37. /**
  38. * Search
  39. *
  40. * @return array
  41. * @param mixed $id Optional
  42. */
  43. public function search($query) {
  44. if (is_array($query)) {
  45. /**
  46. * Array implies using the JSON query DSL
  47. */
  48. $url = $this->buildUrl(array(
  49. $this->type, "_search"
  50. ));
  51. try {
  52. $result = $this->call($url, "GET", $query);
  53. }
  54. catch (Exception $e) {
  55. throw $e;
  56. }
  57. }
  58. elseif (is_string($query)) {
  59. /**
  60. * String based search means http query string search
  61. */
  62. $url = $this->buildUrl(array(
  63. $this->type, "_search?q=" . $query
  64. ));
  65. try {
  66. $result = $this->call($url, "GET");
  67. }
  68. catch (Exception $e) {
  69. throw $e;
  70. }
  71. }
  72. return $result;
  73. }
  74. /**
  75. * Search
  76. *
  77. * @return array
  78. * @param mixed $id Optional
  79. * @param array $options Parameters to pass to delete action
  80. */
  81. public function deleteByQuery($query, array $options = array()) {
  82. if (is_array($query)) {
  83. /**
  84. * Array implies using the JSON query DSL
  85. */
  86. $url = $this->buildUrl(array(
  87. $this->type, "_query"
  88. ), $options);
  89. try {
  90. $result = $this->call($url, "DELETE", $query);
  91. }
  92. catch (Exception $e) {
  93. throw $e;
  94. }
  95. }
  96. elseif (is_string($query)) {
  97. /**
  98. * String based search means http query string search
  99. */
  100. $url = $this->buildUrl(array(
  101. $this->type, "_query?q=" . $query
  102. ), $options);
  103. try {
  104. $result = $this->call($url, "DELETE");
  105. }
  106. catch (Exception $e) {
  107. throw $e;
  108. }
  109. }
  110. return $result['ok'];
  111. }
  112. /**
  113. * Perform a request against the given path/method/payload combination
  114. * Example:
  115. * $es->request('/_status');
  116. *
  117. * @param string|array $path
  118. * @param string $method
  119. * @param array|false $payload
  120. * @return array
  121. */
  122. public function request($path, $method="GET", $payload=false) {
  123. $url = $this->buildUrl($path);
  124. try {
  125. $result = $this->call($url, $method, $payload);
  126. }
  127. catch (Exception $e) {
  128. throw $e;
  129. }
  130. return $result;
  131. }
  132. /**
  133. * Flush this index/type combination
  134. *
  135. * @return array
  136. * @param mixed $id Id of document to delete
  137. * @param array $options Parameters to pass to delete action
  138. */
  139. public function delete($id=false, array $options = array()) {
  140. if ($id)
  141. return $this->request(array($this->type, $id), "DELETE");
  142. else
  143. return $this->request(false, "DELETE");
  144. }
  145. /**
  146. * Perform a http call against an url with an optional payload
  147. *
  148. * @return array
  149. * @param string $url
  150. * @param string $method (GET/POST/PUT/DELETE)
  151. * @param array $payload The document/instructions to pass along
  152. */
  153. protected function call($url, $method="GET", $payload=false) {
  154. $conn = $this->ch;
  155. $protocol = "http";
  156. $requestURL = $protocol . "://" . $this->host . $url;
  157. curl_setopt($conn, CURLOPT_URL, $requestURL);
  158. curl_setopt($conn, CURLOPT_TIMEOUT, self::TIMEOUT);
  159. curl_setopt($conn, CURLOPT_PORT, $this->port);
  160. curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1) ;
  161. curl_setopt($conn, CURLOPT_CUSTOMREQUEST, strtoupper($method));
  162. curl_setopt($conn, CURLOPT_FORBID_REUSE , 0) ;
  163. if (is_array($payload) && count($payload) > 0)
  164. curl_setopt($conn, CURLOPT_POSTFIELDS, json_encode($payload)) ;
  165. else
  166. curl_setopt($conn, CURLOPT_POSTFIELDS, null);
  167. $data = curl_exec($conn);
  168. if ($data !== false)
  169. $data = json_decode($data, true);
  170. else
  171. {
  172. /**
  173. * cUrl error code reference can be found here:
  174. * http://curl.haxx.se/libcurl/c/libcurl-errors.html
  175. */
  176. $errno = curl_errno($conn);
  177. switch ($errno)
  178. {
  179. case CURLE_UNSUPPORTED_PROTOCOL:
  180. $error = "Unsupported protocol [$protocol]";
  181. break;
  182. case CURLE_FAILED_INIT:
  183. $error = "Internal cUrl error?";
  184. break;
  185. case CURLE_URL_MALFORMAT:
  186. $error = "Malformed URL [$requestURL] -d " . json_encode($payload);
  187. break;
  188. case CURLE_COULDNT_RESOLVE_PROXY:
  189. $error = "Couldnt resolve proxy";
  190. break;
  191. case CURLE_COULDNT_RESOLVE_HOST:
  192. $error = "Couldnt resolve host";
  193. break;
  194. case CURLE_COULDNT_CONNECT:
  195. $error = "Couldnt connect to host [{$this->host}], ElasticSearch down?";
  196. break;
  197. case CURLE_OPERATION_TIMEDOUT:
  198. $error = "Operation timed out on [$requestURL]";
  199. break;
  200. default:
  201. $error = "Unknown error";
  202. if ($errno == 0)
  203. $error .= ". Non-cUrl error";
  204. break;
  205. }
  206. $exception = new ElasticSearchTransportHTTPException($error);
  207. $exception->payload = $payload;
  208. $exception->port = $this->port;
  209. $exception->protocol = $protocol;
  210. $exception->host = $this->host;
  211. $exception->method = $method;
  212. throw $exception;
  213. }
  214. if (array_key_exists('error', $data))
  215. $this->handleError($url, $method, $payload, $data);
  216. return $data;
  217. }
  218. protected function handleError($url, $method, $payload, $response) {
  219. $err = "Request: \n";
  220. $err .= "curl -X$method http://{$this->host}:{$this->port}$url";
  221. if ($payload) $err .= " -d '" . json_encode($payload) . "'";
  222. $err .= "\n";
  223. $err .= "Triggered some error: \n";
  224. $err .= $response['error'] . "\n";
  225. //echo $err;
  226. }
  227. }