summaryrefslogtreecommitdiffstats
path: root/library/Director/RestApi/RestApiClient.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/Director/RestApi/RestApiClient.php311
1 files changed, 311 insertions, 0 deletions
diff --git a/library/Director/RestApi/RestApiClient.php b/library/Director/RestApi/RestApiClient.php
new file mode 100644
index 0000000..2ebc4d4
--- /dev/null
+++ b/library/Director/RestApi/RestApiClient.php
@@ -0,0 +1,311 @@
+<?php
+
+namespace Icinga\Module\Director\RestApi;
+
+use Icinga\Module\Director\Core\Json;
+use InvalidArgumentException;
+use RuntimeException;
+
+class RestApiClient
+{
+ /** @var resource */
+ private $curl;
+
+ /** @var string HTTP or HTTPS */
+ private $scheme;
+
+ /** @var string */
+ private $host;
+
+ /** @var int */
+ private $port;
+
+ /** @var string */
+ private $user;
+
+ /** @var string */
+ private $pass;
+
+ /** @var bool */
+ private $verifySslPeer = true;
+
+ /** @var bool */
+ private $verifySslHost = true;
+
+ /** @var string */
+ private $proxy;
+
+ /** @var string */
+ private $proxyType;
+
+ /** @var string */
+ private $proxyUser;
+
+ /** @var string */
+ private $proxyPass;
+
+ /** @var array */
+ private $proxyTypes = [
+ 'HTTP' => CURLPROXY_HTTP,
+ 'SOCKS5' => CURLPROXY_SOCKS5,
+ ];
+
+ /**
+ * RestApiClient constructor.
+ *
+ * Please note that only the host is required, user and pass are optional
+ *
+ * @param string $host
+ * @param string|null $user
+ * @param string|null $pass
+ */
+ public function __construct($host, $user = null, $pass = null)
+ {
+ $this->host = $host;
+ $this->user = $user;
+ $this->pass = $pass;
+ }
+
+ /**
+ * Use a proxy
+ *
+ * @param $url
+ * @param string $type Either HTTP or SOCKS5
+ * @return $this
+ */
+ public function setProxy($url, $type = 'HTTP')
+ {
+ $this->proxy = $url;
+ if (\is_int($type)) {
+ $this->proxyType = $type;
+ } else {
+ $this->proxyType = $this->proxyTypes[$type];
+ }
+ return $this;
+ }
+
+ /**
+ * @param string $user
+ * @param string $pass
+ * @return $this
+ */
+ public function setProxyAuth($user, $pass)
+ {
+ $this->proxyUser = $user;
+ $this->proxyPass = $pass;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getScheme()
+ {
+ if ($this->scheme === null) {
+ return 'HTTPS';
+ } else {
+ return $this->scheme;
+ }
+ }
+
+ public function setScheme($scheme)
+ {
+ $scheme = \strtoupper($scheme);
+ if (! \in_array($scheme, ['HTTP', 'HTTPS'])) {
+ throw new InvalidArgumentException("Got invalid scheme: $scheme");
+ }
+
+ $this->scheme = $scheme;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPort()
+ {
+ if ($this->port === null) {
+ return $this->getScheme() === 'HTTPS' ? 443 : 80;
+ } else {
+ return $this->port;
+ }
+ }
+
+ /**
+ * @param int|string|null $port
+ * @return $this
+ */
+ public function setPort($port)
+ {
+ if ($port === null) {
+ $this->port = null;
+ return $this;
+ }
+ $port = (int) ($port);
+ if ($port < 1 || $port > 65535) {
+ throw new InvalidArgumentException("Got invalid port: $port");
+ }
+
+ $this->port = $port;
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDefaultPort()
+ {
+ return $this->port === null
+ || $this->getScheme() === 'HTTPS' && $this->getPort() === 443
+ || $this->getScheme() === 'HTTP' && $this->getPort() === 80;
+ }
+
+ /**
+ * @param bool $disable
+ * @return $this
+ */
+ public function disableSslPeerVerification($disable = true)
+ {
+ $this->verifySslPeer = ! $disable;
+ return $this;
+ }
+
+ /**
+ * @param bool $disable
+ * @return $this
+ */
+ public function disableSslHostVerification($disable = true)
+ {
+ $this->verifySslHost = ! $disable;
+ return $this;
+ }
+
+ /**
+ * @param string $url
+ * @return string
+ */
+ public function url($url)
+ {
+ return \sprintf(
+ '%s://%s%s/%s',
+ \strtolower($this->getScheme()),
+ $this->host,
+ $this->isDefaultPort() ? '' : ':' . $this->getPort(),
+ ltrim($url, '/')
+ );
+ }
+
+ /**
+ * @param string $url
+ * @param mixed $body
+ * @param array $headers
+ * @return mixed
+ */
+ public function get($url, $body = null, $headers = [])
+ {
+ return $this->request('get', $url, $body, $headers);
+ }
+
+ /**
+ * @param $url
+ * @param null $body
+ * @param array $headers
+ * @return mixed
+ */
+ public function post($url, $body = null, $headers = [])
+ {
+ return $this->request('post', $url, Json::encode($body), $headers);
+ }
+
+ /**
+ * @param $method
+ * @param $url
+ * @param null $body
+ * @param array $headers
+ * @return mixed
+ */
+ protected function request($method, $url, $body = null, $headers = [])
+ {
+ $sendHeaders = ['Host: ' . $this->host];
+ foreach ($headers as $key => $val) {
+ $sendHeaders[] = "$key: $val";
+ }
+
+ if (! \in_array('Accept', $headers)) {
+ $sendHeaders[] = 'Accept: application/json';
+ }
+
+ $url = $this->url($url);
+ $opts = [
+ CURLOPT_URL => $url,
+ CURLOPT_HTTPHEADER => $sendHeaders,
+ CURLOPT_CUSTOMREQUEST => \strtoupper($method),
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_CONNECTTIMEOUT => 5,
+ ];
+
+ if ($this->getScheme() === 'HTTPS') {
+ $opts[CURLOPT_SSL_VERIFYPEER] = $this->verifySslPeer;
+ $opts[CURLOPT_SSL_VERIFYHOST] = $this->verifySslHost ? 2 : 0;
+ }
+
+ if ($this->user !== null) {
+ $opts[CURLOPT_USERPWD] = \sprintf('%s:%s', $this->user, $this->pass);
+ }
+
+ if ($this->proxy) {
+ $opts[CURLOPT_PROXY] = $this->proxy;
+ $opts[CURLOPT_PROXYTYPE] = $this->proxyType;
+
+ if ($this->proxyUser) {
+ $opts['CURLOPT_PROXYUSERPWD'] = \sprintf(
+ '%s:%s',
+ $this->proxyUser,
+ $this->proxyPass
+ );
+ }
+ }
+
+ if ($body !== null) {
+ $opts[CURLOPT_POSTFIELDS] = $body;
+ }
+
+ $curl = $this->curl();
+ \curl_setopt_array($curl, $opts);
+
+ $res = \curl_exec($curl);
+ if ($res === false) {
+ throw new RuntimeException('CURL ERROR: ' . \curl_error($curl));
+ }
+
+ $statusCode = \curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ if ($statusCode === 401) {
+ throw new RuntimeException(
+ 'Unable to authenticate, please check your REST API credentials'
+ );
+ }
+
+ if ($statusCode >= 400) {
+ throw new RuntimeException(
+ "Got $statusCode: " . \var_export($res, 1)
+ );
+ }
+
+ return Json::decode($res);
+ }
+
+ /**
+ * @return resource
+ */
+ protected function curl()
+ {
+ if ($this->curl === null) {
+ $this->curl = \curl_init(\sprintf('https://%s:%d', $this->host, $this->port));
+ if (! $this->curl) {
+ throw new RuntimeException('CURL INIT ERROR: ' . \curl_error($this->curl));
+ }
+ }
+
+ return $this->curl;
+ }
+}