Handle invalid Icinga 2 API response types

refs #2728
This commit is contained in:
Alexander A. Klimov 2017-02-09 13:38:43 +01:00
parent 80d3abed9d
commit 6fbec7134c
3 changed files with 70 additions and 30 deletions

View File

@ -8,6 +8,7 @@ use Icinga\Module\Monitoring\Command\IcingaApiCommand;
use Icinga\Module\Monitoring\Command\IcingaCommand;
use Icinga\Module\Monitoring\Command\Renderer\IcingaApiCommandRenderer;
use Icinga\Module\Monitoring\Exception\CommandTransportException;
use Icinga\Module\Monitoring\Exception\JsonDecodeException;
use Icinga\Module\Monitoring\Web\Rest\RestRequest;
/**
@ -193,12 +194,18 @@ class ApiCommandTransport implements CommandTransportInterface
$this->getHost(),
$this->getPort()
);
$response = RestRequest::post($this->getUriFor($command->getEndpoint()))
->authenticateWith($this->getUsername(), $this->getPassword())
->sendJson()
->noStrictSsl()
->setPayload($command->getData())
->send();
try {
$response = RestRequest::post($this->getUriFor($command->getEndpoint()))
->authenticateWith($this->getUsername(), $this->getPassword())
->sendJson()
->noStrictSsl()
->setPayload($command->getData())
->send();
} catch (JsonDecodeException $e) {
throw new CommandTransportException('Got invalid JSON response from the Icinga 2 API: %s', $e->getMessage());
}
if (isset($response['error'])) {
throw new CommandTransportException(
'Can\'t send external Icinga command: %u %s',

View File

@ -0,0 +1,55 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Exception;
use Icinga\Exception\IcingaException;
/**
* Exception thrown if {@link json_decode()} fails
*/
class JsonDecodeException extends IcingaException
{
/**
* JsonDecodeException constructor
*
* @param string $invalidJson The JSON string caused this error
* @param int|null $jsonError Error code (from {@link json_last_error()}) or null for the last occurred error
*/
public function __construct($invalidJson, $jsonError = null)
{
if ($jsonError === null) {
$msg = version_compare(PHP_VERSION, '5.5.0', '>=')
? json_last_error_msg()
: $this->errorCodeToMessage(json_last_error());
} else {
$msg = $this->errorCodeToMessage($jsonError);
}
parent::__construct('%s: %s', $msg, $invalidJson);
}
/**
* Convert the given error code (from {@link json_last_error()}) to a human readable error message
*
* @param int $jsonError
* @return string
*/
protected function errorCodeToMessage($jsonError)
{
switch ($jsonError) {
case JSON_ERROR_DEPTH:
return 'The maximum stack depth has been exceeded';
case JSON_ERROR_CTRL_CHAR:
return 'Control character error, possibly incorrectly encoded';
case JSON_ERROR_STATE_MISMATCH:
return 'Invalid or malformed JSON';
case JSON_ERROR_SYNTAX:
return 'Syntax error';
case JSON_ERROR_UTF8:
return 'Malformed UTF-8 characters, possibly incorrectly encoded';
default:
return 'An error occured when parsing a JSON string';
}
}
}

View File

@ -5,6 +5,7 @@ namespace Icinga\Module\Monitoring\Web\Rest;
use Exception;
use Icinga\Application\Logger;
use Icinga\Module\Monitoring\Exception\JsonDecodeException;
/**
* REST Request
@ -264,30 +265,7 @@ class RestRequest
$response = @json_decode($result, true);
if ($response === null) {
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
throw new Exception(json_last_error_msg());
} else {
switch (json_last_error()) {
case JSON_ERROR_DEPTH:
$msg = 'The maximum stack depth has been exceeded';
break;
case JSON_ERROR_CTRL_CHAR:
$msg = 'Control character error, possibly incorrectly encoded';
break;
case JSON_ERROR_STATE_MISMATCH:
$msg = 'Invalid or malformed JSON';
break;
case JSON_ERROR_SYNTAX:
$msg = 'Syntax error';
break;
case JSON_ERROR_UTF8:
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
break;
default:
$msg = 'An error occured when parsing a JSON string';
}
throw new Exception($msg);
}
throw new JsonDecodeException($result);
}
return $response;