Laravel.io
<?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;
    }
}

Please note that all pasted data is publicly available.