<?php namespace OpenObjects\Component\Http; use GuzzleHttp\Client; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Exception\ClientException; use InvalidArgumentException; /** * RESTful class is responsible for interfacing with the Guzzle * HTTP client to make requests to external sources. * * Class RESTfulService * @package OpenObjects\Component\Http */ class RESTfulService { /** * The API endpoint. * * @var string */ protected $endpoint = null; /** * The response body as a string. * * @var string */ protected $responseBody; /** * The Guzzle HTTP client. * * @var Client; */ protected $guzzleHttpClient; /** * @var */ protected $httpClientResponse = null; /** * The format the requests should return in. * * @var string json|xml */ protected $responseFormat = 'json'; /** * @var bool */ protected $asyncRequest = false; /** * RESTfulService constructor. * * @param $endpoint * @param Client $client */ public function __construct($endpoint, Client $client) { // Assign endpoint for the request. $this->endpoint = $endpoint; // Assign Guzzles client to class property. $this->setClient($client); } /** * Get guzzleHttpClient. * * @return Client */ public function getClient() { return $this->guzzleHttpClient; } /** * Set guzzleHttpClient. * * @param Client $guzzleHttpClient */ public function setClient($guzzleHttpClient) { $this->guzzleHttpClient = $guzzleHttpClient; } /** * Get httpClientResponse. * * @return Response */ public function getHttpClientResponse() { return $this->httpClientResponse; } /** * Set httpClientResponse. * * @param Response $httpClientResponse * @return $this */ public function setHttpClientResponse(Response $httpClientResponse) { $this->httpClientResponse = $httpClientResponse; return $this; } /** * Get responseBody. * * @return string */ public function getResponseBody() { if (!$this->getHttpClientResponse()) { return null; } $body = (string)$this->getHttpClientResponse()->getBody(); $json = json_decode($body, true); if (json_last_error() == JSON_ERROR_NONE) { if (isset($json['error'])) { return $json['error']; } return $json; } return $body; } /** * Get responseFormat. * * @return Client */ public function getResponseFormat() { return $this->responseFormat; } /** * Set responseFormat. * * @param string $responseFormat */ public function setResponseFormat($responseFormat) { $this->responseFormat = $responseFormat; } /** * @param bool $isAsync * @return $this */ public function setAsyncRequest($isAsync) { $this->asyncRequest = $isAsync; return $this; } /** * @return bool */ public function isAsyncRequest() { return $this->asyncRequest; } /** * Make an HTTP call to the external resource. * * @param string $method The HTTP method * @param array $args An array of parameters * * @return object */ public function __call($method, $args) { if (count($args) < 1) { throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; $opts = isset($args[1]) ? $args[1] : []; return $this->requestBroker($method, $uri, $opts); } /** * @return string */ protected function getEndPoint() { return $this->endpoint; } /** * @param $endpoint * @return $this */ protected function setEndpoint($endpoint = null) { if ($endpoint !== null) { $this->endpoint = $endpoint; } return $this; } /** * Send the post request and return the array result of the the response data. * * @param string $action * @param string $verb * @param array $params * * @return object|boolean */ protected function requestBroker($action, $verb = null, array $params = []) { try { if (false === $this->isAsyncRequest()) { // Send the POST request using the client. $response = $this->guzzleHttpClient->$action( $this->getEndPoint() . $verb, $params ); } else { // Send an asynchronous request. $headers = isset($params['headers']) ? $params['headers'] : []; $body = isset($params['body']) ? $params['body'] : []; $request = new Request($action, $this->getEndPoint() . $verb, $headers, $body); $promise = $this->guzzleHttpClient->sendAsync($request)->then(function ( $response ) { $this->setHttpClientResponse($response); }); $promise->wait(); } $this->setHttpClientResponse($response); // Catch empty an empty response body. if ('' == (string) $response->getBody() && $this->getResponseFormat() != 'file') { return json_encode($response->getHeaders()); } switch ($this->getResponseFormat()) { case 'raw': return (string) $response->getBody(); break; case 'array': return json_decode((string) $response->getBody(), true); break; case 'json': return json_encode((string) $response->getBody()); break; case 'xml': return simplexml_load_string((string) $response->getBody()); break; case 'file': return $response; break; default: return json_encode($response->getHeaders()); } } catch (ClientException $e) { if ($e->getResponse() !== null) { $this->setHttpClientResponse($e->getResponse()); } return false; } catch (\Exception $e) { if ($e->getResponse() !== null) { $this->setHttpClientResponse($e->getResponse()); } return false; } return $response; } }