258 lines
4.5 KiB
PHP
258 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace Analyst;
|
|
|
|
use Exception;
|
|
use Analyst\Contracts\HttpClientContract;
|
|
use Analyst\Contracts\RequestorContract;
|
|
|
|
class ApiRequestor implements RequestorContract
|
|
{
|
|
/**
|
|
* Supported http client
|
|
*
|
|
* @var HttpClientContract
|
|
*/
|
|
protected $httpClient;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $clientId;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $clientSecret;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $apiBase;
|
|
|
|
/**
|
|
* Default headers to be sent
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $defaultHeaders = [
|
|
'accept' => 'application/json',
|
|
'content-type' => 'application/json'
|
|
];
|
|
|
|
/**
|
|
* Prioritized http clients
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $availableClients = [
|
|
'Analyst\Http\WordPressHttpClient',
|
|
'Analyst\Http\CurlHttpClient',
|
|
'Analyst\Http\DummyHttpClient',
|
|
];
|
|
|
|
/**
|
|
* ApiRequestor constructor.
|
|
* @param $id
|
|
* @param $secret
|
|
* @param $apiBase
|
|
* @throws \Exception
|
|
*/
|
|
public function __construct($id, $secret, $apiBase)
|
|
{
|
|
$this->clientId = $id;
|
|
$this->clientSecret = $secret;
|
|
|
|
$this->setApiBase($apiBase);
|
|
|
|
$this->httpClient = $this->resolveHttpClient();
|
|
}
|
|
|
|
/**
|
|
* Set api base url
|
|
*
|
|
* @param $url
|
|
*/
|
|
public function setApiBase($url)
|
|
{
|
|
$this->apiBase = $url;
|
|
}
|
|
|
|
/**
|
|
* Get request
|
|
*
|
|
* @param $url
|
|
* @param array $headers
|
|
* @return mixed
|
|
*/
|
|
public function get($url, $headers = [])
|
|
{
|
|
return $this->request('GET', $url, null, $headers);
|
|
}
|
|
|
|
/**
|
|
* Post request
|
|
*
|
|
* @param $url
|
|
* @param $body
|
|
* @param array $headers
|
|
* @return mixed
|
|
*/
|
|
public function post($url, $body = [], $headers = [])
|
|
{
|
|
return $this->request('POST', $url, $body, $headers);
|
|
}
|
|
|
|
/**
|
|
* Put request
|
|
*
|
|
* @param $url
|
|
* @param $body
|
|
* @param array $headers
|
|
* @return mixed
|
|
*/
|
|
public function put($url, $body = [], $headers = [])
|
|
{
|
|
return $this->request('PUT', $url, $body, $headers);
|
|
}
|
|
|
|
/**
|
|
* Delete request
|
|
*
|
|
* @param $url
|
|
* @param array $headers
|
|
* @return mixed
|
|
*/
|
|
public function delete($url, $headers = [])
|
|
{
|
|
return $this->request('DELETE', $url, null, $headers);
|
|
}
|
|
|
|
/**
|
|
* Make request to api
|
|
*
|
|
* @param $method
|
|
* @param $url
|
|
* @param array $body
|
|
* @param array $headers
|
|
* @return mixed
|
|
*/
|
|
protected function request($method, $url, $body = [], $headers = [])
|
|
{
|
|
$fullUrl = $this->resolveFullUrl($url);
|
|
|
|
$date = date('r', time());
|
|
|
|
$headers['date'] = $date;
|
|
$headers['signature'] = $this->resolveSignature($this->clientSecret, $method, $fullUrl, $body, $date);
|
|
|
|
// Lowercase header names
|
|
$headers = $this->prepareHeaders(
|
|
array_merge($headers, $this->defaultHeaders)
|
|
);
|
|
|
|
$response = $this->httpClient->request($method, $fullUrl, $body, $headers);
|
|
|
|
// TODO: Check response code and take actions
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Set one default header
|
|
*
|
|
* @param $header
|
|
* @param $value
|
|
*/
|
|
public function setDefaultHeader($header, $value)
|
|
{
|
|
$this->defaultHeaders[
|
|
$this->resolveValidHeaderName($header)
|
|
] = $value;
|
|
}
|
|
|
|
/**
|
|
* Resolves supported http client
|
|
*
|
|
* @return HttpClientContract
|
|
* @throws Exception
|
|
*/
|
|
protected function resolveHttpClient()
|
|
{
|
|
$clients = array_filter($this->availableClients, $this->guessClientSupportEnvironment());
|
|
|
|
if (!isset($clients[0])) {
|
|
throw new Exception('There is no http client which this application can support');
|
|
}
|
|
|
|
// Instantiate first supported http client
|
|
return new $clients[0];
|
|
}
|
|
|
|
/**
|
|
* This will filter out clients which is not supported
|
|
* by the current environment
|
|
*
|
|
* @return \Closure
|
|
*/
|
|
protected function guessClientSupportEnvironment()
|
|
{
|
|
return function ($client) {
|
|
return forward_static_call([$client, 'hasSupport']);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Resolves valid header name
|
|
*
|
|
* @param $headerName
|
|
* @return string
|
|
*/
|
|
private function resolveValidHeaderName($headerName)
|
|
{
|
|
return strtolower($headerName);
|
|
}
|
|
|
|
/**
|
|
* Lowercase header names
|
|
*
|
|
* @param $headers
|
|
* @return array
|
|
*/
|
|
private function prepareHeaders($headers)
|
|
{
|
|
return array_change_key_case($headers, CASE_LOWER);
|
|
}
|
|
|
|
/**
|
|
* Sign request
|
|
*
|
|
* @param $key
|
|
* @param $method
|
|
* @param $url
|
|
* @param $body
|
|
* @param $date
|
|
*
|
|
* @return false|string
|
|
*/
|
|
private function resolveSignature($key, $method, $url, $body, $date)
|
|
{
|
|
$string = implode('\n', [$method, $url, md5(json_encode($body)), $date]);
|
|
|
|
$contentSecret = hash_hmac('sha256', $string, $key);
|
|
|
|
return sprintf('%s:%s', $this->clientId, $contentSecret);
|
|
}
|
|
|
|
/**
|
|
* Compose full url
|
|
*
|
|
* @param $url
|
|
* @return string
|
|
*/
|
|
private function resolveFullUrl($url)
|
|
{
|
|
return sprintf('%s/%s', $this->apiBase, trim($url, '/'));
|
|
}
|
|
}
|