Skip to content

Commit

Permalink
Improved error handling for curl errors in http transport. Throws exc…
Browse files Browse the repository at this point in the history
…eption with meaningful error message
  • Loading branch information
Raymond Julin committed Sep 17, 2010
1 parent 1ebce32 commit edc6fc0
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 12 deletions.
1 change: 1 addition & 0 deletions ElasticSearchClient.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php // vim:set ts=4 sw=4 et:
require_once 'lib/ElasticSearchException.php';
require_once 'lib/ElasticSearchDSLStringify.php';

require_once 'lib/builder/ElasticSearchDSLBuilder.php';
Expand Down
3 changes: 3 additions & 0 deletions lib/ElasticSearchException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php
class ElasticSearchException extends Exception {
}
122 changes: 110 additions & 12 deletions lib/transport/ElasticSearchTransportHTTP.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
<?php
if (!defined('CURLE_OPERATION_TIMEDOUT'))
define('CURLE_OPERATION_TIMEDOUT', 28);

class ElasticSearchTransportHTTPException extends ElasticSearchException {
protected $payload;
public function setPayload($payload) {
$this->payload = $payload;
}
public function getPayload() {
return $this->payload;
}
}

class ElasticSearchTransportHTTP extends ElasticSearchTransport {
private $host = "", $port = 9200;

/**
* How long before timing out CURL call
*/
const TIMEOUT = 5;

/**
* What host to connect to for server
* @var string
*/
protected $host = "";

/**
* Port to connect on
* @var int
*/
protected $port = 9200;
public function __construct($host, $port) {
$this->host = $host;
$this->port = $port;
Expand All @@ -17,7 +45,12 @@ public function __construct($host, $port) {
public function index($document, $id=false) {
$url = $this->buildUrl(array($this->type, $id));
$method = ($id == false) ? "POST" : "PUT";
$response = $this->call($url, $method, $document );
try {
$response = $this->call($url, $method, $document);
}
catch (Exception $e) {
throw $e;
}

return $response;
}
Expand All @@ -36,7 +69,12 @@ public function search($query) {
$url = $this->buildUrl(array(
$this->type, "_search"
));
$result = $this->call($url, "GET", $query);
try {
$result = $this->call($url, "GET", $query);
}
catch (Exception $e) {
throw $e;
}
}
elseif (is_string($query)) {
/**
Expand All @@ -46,6 +84,12 @@ public function search($query) {
$this->type, "_search?q=" . $query
));
$result = $this->call($url, "GET");
try {
$result = $this->call($url, "GET");
}
catch (Exception $e) {
throw $e;
}
}
return $result;
}
Expand All @@ -64,7 +108,12 @@ public function deleteByQuery($query) {
$url = $this->buildUrl(array(
$this->type, "_query"
));
$result = $this->call($url, "DELETE", $query);
try {
$result = $this->call($url, "DELETE", $query);
}
catch (Exception $e) {
throw $e;
}
}
elseif (is_string($query)) {
/**
Expand All @@ -73,7 +122,12 @@ public function deleteByQuery($query) {
$url = $this->buildUrl(array(
$this->type, "_query?q=" . $query
));
$result = $this->call($url, "DELETE");
try {
$result = $this->call($url, "DELETE");
}
catch (Exception $e) {
throw $e;
}
}
return $result['ok'];
}
Expand All @@ -86,7 +140,13 @@ public function deleteByQuery($query) {
*/
public function request($path, $method="GET") {
$url = $this->buildUrl($path);
return $this->call($url, $method);
try {
$result = $this->call($url, $method);
}
catch (Exception $e) {
throw $e;
}
return $result;
}

/**
Expand All @@ -109,9 +169,12 @@ public function delete($id=false) {
* @param string $method (GET/POST/PUT/DELETE)
* @param array $payload The document/instructions to pass along
*/
private function call($url, $method="GET", $payload=false) {
protected function call($url, $method="GET", $payload=false) {
$conn = curl_init();
curl_setopt($conn, CURLOPT_URL, "http://" . $this->host . $url);
$protocol = "http";
$requestURL = $protocol . "://" . $this->host . $url;
curl_setopt($conn, CURLOPT_URL, $requestURL);
curl_setopt($conn, CURLOPT_TIMEOUT, self::TIMEOUT);
curl_setopt($conn, CURLOPT_PORT, $this->port);
curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($conn, CURLOPT_CUSTOMREQUEST, strtoupper($method));
Expand All @@ -124,8 +187,43 @@ private function call($url, $method="GET", $payload=false) {
$data = json_decode($data, true);
else
{
$postData = json_encode($payload);
throw new Exception("Transport call to API failed on payload [$postData]");
/**
* cUrl error code reference can be found here:
* http://curl.haxx.se/libcurl/c/libcurl-errors.html
*/
$errno = curl_errno($conn);
switch ($errno)
{
case CURLE_UNSUPPORTED_PROTOCOL:
$error = "Unsupported protocol [$protocol]";
break;
case CURLE_FAILED_INIT:
$error = "Internal cUrl error?";
break;
case CURLE_URL_MALFORMAT:
$error = "Malformed URL [$requestURL] -d " . json_encode($payload);
break;
case CURLE_COULDNT_RESOLVE_PROXY:
$error = "Couldnt resolve proxy";
break;
case CURLE_COULDNT_RESOLVE_HOST:
$error = "Couldnt resolve host";
break;
case CURLE_COULDNT_CONNECT:
$error = "Couldnt connect to host [{$this->host}], ElasticSearch down?";
break;
case CURLE_OPERATION_TIMEDOUT:
$error = "Operation timed out on [$requestURL]";
break;
default:
$error = "Unknown error";
if ($errno == 0)
$error .= ". Non-cUrl error";
break;
}
$exception = new ElasticSearchTransportHTTPException($error);
$exception->setPayload($payload);
throw $exception;
}

if (array_key_exists('error', $data))
Expand All @@ -134,7 +232,7 @@ private function call($url, $method="GET", $payload=false) {
return $data;
}

private function handleError($url, $method, $payload, $response) {
protected function handleError($url, $method, $payload, $response) {
$err = "Request: \n";
$err .= "curl -X$method http://{$this->host}:{$this->port}$url";
if ($payload) $err .= " -d '" . json_encode($payload) . "'";
Expand All @@ -150,7 +248,7 @@ private function handleError($url, $method, $payload, $response) {
* @return string
* @param array $path
*/
private function buildUrl($path=false) {
protected function buildUrl($path=false) {
$url = "/" . $this->index;
if ($path && count($path) > 0)
$url .= "/" . implode("/", array_filter($path));
Expand Down
10 changes: 10 additions & 0 deletions tests/HTTPTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,14 @@ public function testSlightlyComplexSearch() {
));
$this->assertEquals(3, $hits['hits']['total']);
}


/**
* @expectedException ElasticSearchTransportHTTPException
*/
public function testSearchThrowExceptionWhenServerDown() {
$transport = new ElasticSearchTransportHTTP("localhost", 9300);
$search = new ElasticSearchClient($transport, "test-index", "test-type");
$search->search("title:cool");
}
}

0 comments on commit edc6fc0

Please sign in to comment.