diff options
Diffstat (limited to '')
-rw-r--r-- | modules/monitoring/library/Monitoring/Web/Rest/RestRequest.php | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/modules/monitoring/library/Monitoring/Web/Rest/RestRequest.php b/modules/monitoring/library/Monitoring/Web/Rest/RestRequest.php new file mode 100644 index 0000000..fcbe0ca --- /dev/null +++ b/modules/monitoring/library/Monitoring/Web/Rest/RestRequest.php @@ -0,0 +1,297 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Web\Rest; + +use Exception; +use Icinga\Application\Logger; +use Icinga\Util\Json; +use Icinga\Module\Monitoring\Exception\CurlException; + +/** + * REST Request + */ +class RestRequest +{ + /** + * Request URI + * + * @var string + */ + protected $uri; + + /** + * Request method + * + * @var string + */ + protected $method; + + /** + * Request content type + * + * @var string + */ + protected $contentType; + + /** + * Whether to authenticate with basic auth + * + * @var bool + */ + protected $hasBasicAuth; + + /** + * Auth username + * + * @var string + */ + protected $username; + + /** + * Auth password + * + * @var string + */ + protected $password; + + /** + * Request payload + * + * @var mixed + */ + protected $payload; + + /** + * Whether strict SSL is enabled + * + * @var bool + */ + protected $strictSsl = true; + + /** + * Request timeout + * + * @var int + */ + protected $timeout = 30; + + /** + * Create a GET REST request + * + * @param string $uri + * + * @return static + */ + public static function get($uri) + { + $request = new static; + $request->uri = $uri; + $request->method = 'GET'; + return $request; + } + + /** + * Create a POST REST request + * + * @param string $uri + * + * @return static + */ + public static function post($uri) + { + $request = new static; + $request->uri = $uri; + $request->method = 'POST'; + return $request; + } + + /** + * Send content type JSON + * + * @return $this + */ + public function sendJson() + { + $this->contentType = 'application/json'; + + return $this; + } + + /** + * Set basic auth credentials + * + * @param string $username + * @param string $password + * + * @return $this + */ + public function authenticateWith($username, $password) + { + $this->hasBasicAuth = true; + $this->username = $username; + $this->password = $password; + + return $this; + } + + /** + * Set request payload + * + * @param mixed $payload + * + * @return $this + */ + public function setPayload($payload) + { + $this->payload = $payload; + + return $this; + } + + /** + * Disable strict SSL + * + * @return $this + */ + public function noStrictSsl() + { + $this->strictSsl = false; + + return $this; + } + + /** + * Serialize payload according to content type + * + * @param mixed $payload + * @param string $contentType + * + * @return string + */ + public function serializePayload($payload, $contentType) + { + switch ($contentType) { + case 'application/json': + $payload = Json::encode($payload); + break; + } + + return $payload; + } + + /** + * Send the request + * + * @return mixed + * + * @throws Exception + */ + public function send() + { + $defaults = array( + 'host' => 'localhost', + 'path' => '/' + ); + + $url = array_merge($defaults, parse_url($this->uri)); + + if (isset($url['port'])) { + $url['host'] .= sprintf(':%u', $url['port']); + } + + if (isset($url['query'])) { + $url['path'] .= sprintf('?%s', $url['query']); + } + + $headers = array( + "{$this->method} {$url['path']} HTTP/1.1", + "Host: {$url['host']}", + "Content-Type: {$this->contentType}", + 'Accept: application/json', + // Bypass "Expect: 100-continue" timeouts + 'Expect:' + ); + + $options = array( + CURLOPT_URL => $this->uri, + CURLOPT_TIMEOUT => $this->timeout, + // Ignore proxy settings + CURLOPT_PROXY => '', + CURLOPT_CUSTOMREQUEST => $this->method + ); + + // Record cURL command line for debugging + $curlCmd = array('curl', '-s', '-X', $this->method, '-H', escapeshellarg('Accept: application/json')); + + if ($this->strictSsl) { + $options[CURLOPT_SSL_VERIFYHOST] = 2; + $options[CURLOPT_SSL_VERIFYPEER] = true; + } else { + $options[CURLOPT_SSL_VERIFYHOST] = false; + $options[CURLOPT_SSL_VERIFYPEER] = false; + $curlCmd[] = '-k'; + } + + if ($this->hasBasicAuth) { + $options[CURLOPT_USERPWD] = sprintf('%s:%s', $this->username, $this->password); + $curlCmd[] = sprintf('-u %s:%s', escapeshellarg($this->username), escapeshellarg($this->password)); + } + + if (! empty($this->payload)) { + $payload = $this->serializePayload($this->payload, $this->contentType); + $options[CURLOPT_POSTFIELDS] = $payload; + $curlCmd[] = sprintf('-d %s', escapeshellarg($payload)); + } + + $options[CURLOPT_HTTPHEADER] = $headers; + + $stream = null; + $logger = Logger::getInstance(); + if ($logger !== null && $logger->getLevel() === Logger::DEBUG) { + $stream = fopen('php://temp', 'w'); + $options[CURLOPT_VERBOSE] = true; + $options[CURLOPT_STDERR] = $stream; + } + + Logger::debug( + 'Executing %s %s', + implode(' ', $curlCmd), + escapeshellarg($this->uri) + ); + + $result = $this->curlExec($options); + + if (is_resource($stream)) { + rewind($stream); + Logger::debug(stream_get_contents($stream)); + fclose($stream); + } + + return Json::decode($result, true); + } + + /** + * Set up a new cURL handle with the given options and call {@link curl_exec()} + * + * @param array $options + * + * @return string The response + * + * @throws CurlException + */ + protected function curlExec(array $options) + { + $ch = curl_init(); + $options[CURLOPT_RETURNTRANSFER] = true; + curl_setopt_array($ch, $options); + $result = curl_exec($ch); + + if ($result === false) { + throw new CurlException('%s', curl_error($ch)); + } + + curl_close($ch); + return $result; + } +} |