Get a response given some parameters.
Return an array with the status code and the body.

@param string $url
@param string $method
@param array  $query
@param array  $body
@param array  $server

@return array

@throws ConnectionException
175904
public function get(
        string $url,
        string $method,
        array $query = [],
        array $body = [],
        array $server = []
    ): array {
        $method = strtolower($method);
        $requestParts = $this->buildRequestParts(
            $url,
            $query,
            $body,
            $server
        );

        return $this->tryRequest(function () use ($method, $requestParts) {
            return $this
                ->httpAdapter
                ->getByRequestParts(
                    $this->host,
                    $method,
                    $requestParts
                );
        }, $this
            ->retryMap
            ->getRetry(
                $url,
                $method
            )
        );
    }
583320
public function handle(string $method, $body = false, $uriAppend = false, array $queryParams = [])
    {
        $client   = $this->createElasticClient();
        $param    = $queryParams[0];
        $endPoint = "search";

        if (is_a($param, Search::class)) {
            $endPoint    = "search";
            $queryParams = $param->getParams();

        } elseif (is_a($param, MSearch::class)) {
            $endPoint    = "msearch";
            $queryParams = $param->getParams();
        }

        try {
            $elasticData = $client->{$endPoint}($queryParams);

            if ($client->transport->getLastConnection()) {
                $elasticData['debug'] = $client->transport->getLastConnection()->getLastRequestInfo();
            }

            if ($endPoint == 'msearch') {
                foreach ($elasticData['responses'] as $key => $responseItem) {
                    $responseItem['debug'] = $elasticData['debug'];
                    $response[]            = new Response($responseItem);
                }
            } else {
                $response = new Response($elasticData, $queryParams['body']['size'] ?? 0, $queryParams['body']['from'] ?? 0);
            }
        } catch (\Exception $ex) {
            $error = json_decode($ex->getMessage());
            throw new \Exception($error->error->reason ?? $ex->getMessage());
        }

        return $response;
    }
507384
protected function response_data($result, $method, $url)
    {
        if (isset($result['$data'])) {
            if (is_array($result['$data'])) {
                return Resource::instance($result, $this);
            }
            return $result['$data'];
        }
        return null;
    }
280169
public function connecting($url, $params, $method)
    {
        if ($this->config === null) {
            return null;
        }
        try {
            $result = $this->client->request(
                $method,
                $url,
                [
                'auth' => [
                  $this->username,
                  $this->password,
                ],
                'form_params' => $params,
                ]
            );

            $bodyText = json_decode($result->getBody());

            return $bodyText;
        } catch (ClientException $e) {
            if ($e->hasResponse()) {
                return json_decode($e->getResponse()->getBody())->message;
            }

            return 'Cannot get backup URL.';
        }
    }
234402
public function query($method, array $params = [])
    {
        $rpc = $this->get();
        if (null === $rpc) {
            throw new RPCException(
                "No JsonRPCInterface instances available in the pool."
            );
        }

        return $rpc->query($method, $params);
    }
289059
protected function request($url, $method = 'GET', array $data = [])
    {
        try {
            return call_user_func_array([$this, strtolower($method)], [$url, $data]);
        } catch (\Exception $exception) {
            throw new \RuntimeException('Http method is not valid.');
        }
    }
1159125
protected function query($yql)
    {
        $params = $this->urlParams;
        $params['q'] = $yql;
        $url = $this->url . '?' . http_build_query($params);

        // query the API
        try {
            $response = $this->guzzle->request('GET', $url);
        } catch (TransferException $e) {
            throw new ConnectionException($e->getMessage());
        }

        // process response
        $response = json_decode($response->getBody(), true);

        if (isset($response['query']) && isset($response['query']['results'])) {
            return $response['query']['results'];
        } else {
            throw new ResponseException('Response body is malformed.');
        }
    }
576301
protected function req($url, $method = 'GET', $jsonDecode = TRUE, $body = '') {
    $client = \HPCloud\Transport::instance();
    $headers = array(
        'X-Auth-Token' => $this->token(),
    );

    $raw = $client->doRequest($url, $method, $headers, $body);
    if (!$jsonDecode) {
      return $raw;
    }
    return json_decode($raw->content(), TRUE);

  }
842065
protected function perform($method, $url, $body = array(), $query = array(), $headers = array())
    {

        // response data placeholders
        $response = null;
        $responseHeaders = array();

        $logger = $this->getLogger();

        // determine allowed methods
        $methodName = strtoupper($method);

        // query string processing
        $processedUrl = $this->prepareUrl($url, $query);

        try {

            $logger->debug('NEW REQUEST: ' . $methodName . ' ' . $processedUrl);

            if (!in_array($methodName, array(
                'GET', 'POST', 'PUT', 'DELETE', 'HEAD'
            ))
            ) {
                throw new \Exception('Method not supported', HttpException::METHOD_NOT_SUPPORTED);
            }

            // prepare request headers and fields
            $contextParams = array(
                'http' => array(
                    'method' => $methodName,
                    'ignore_errors' => true   // we want to catch output although the error
                ));

            // skip SSL verification
            if($this->skipSsl){
                $contextParams['ssl'] = array(
                    'verify_peer'=>false,
                    'verify_peer_name'=>false
                );
            }

            // inject request parameters
            $this->applyHeaders($contextParams, $headers);
            $json = !empty($headers['Content-Type']) && $headers['Content-Type']=='application/json';
            $this->applyBody($contextParams, $methodName, $body, $json);

            // make request stream context
            $ctx = stream_context_create($contextParams);

            // initialize requests counter
            $counter = self::$retryLimit;

            $response = null;

            // perform request regarding counter limit and quotas
            while ($counter--) {
                try {
                    // pause upon limits exceeding
                    if (isset($responseHeaders['X-Shop-Api-Calls'])) {

                        $calls = $responseHeaders['X-Shop-Api-Calls'];
                        $limit = $responseHeaders['X-Shop-Api-Limit'];

                        if ($limit - $calls == 0) {
                            sleep(1);
                        }
                    }

                    $response = $this->doRequest($processedUrl, $ctx, $responseHeaders, $methodName);

                    break;
                } catch (\Exception $ex) {
                    // server pauses request for X seconds
                    if (!empty($responseHeaders['Retry-After'])) {
                        if ($counter <= 0) {
                            throw new \Exception('Retries count exceeded', HttpException::QUOTA_EXCEEDED);
                        }
                        sleep($responseHeaders['Retry-After']);
                    } else {
                        // other error
                        throw $ex;
                    }
                }
            }

            $parsedPayload = null;
            if ($methodName != 'HEAD') {
                // try to decode response
                if ($responseHeaders['Content-Type'] == 'application/json') {
                    $parsedPayload = @json_decode($response, true);

                    if (!$parsedPayload && !is_array($parsedPayload)) {
                        throw new \Exception('Result is not a valid JSON', HttpException::MALFORMED_RESULT);
                    }

                } else {
                    $parsedPayload = $response;
                }

                $logger->debug('Response body (decoded): ' . var_export($parsedPayload, true));
            }
        }catch(\Exception $ex){

            $message = $ex->getMessage();

            $logger->error(
                $ex->getMessage(), compact('method', 'url', 'query', 'headers', 'body', 'responseHeaders', 'response')
            );

            if($ex instanceof HttpException){
                $response = $ex->getResponse();
                $message = $ex->getMessage();
            }

            throw new HttpException(
                $message, $ex->getCode(), null, $method, $url, $headers, $query, $body, $response, $responseHeaders
            );
        }

        return array(
            'data' => $parsedPayload,
            'headers' => $responseHeaders
        );
    }
535078
public function sendAsync($method, $uri, $body = null, array $query = [], array $headers = [], array $options = [])
    {
        try {
            $this->validateMethod($method);
        } catch (\InvalidArgumentException $e) {
            return rejection_for($e);
        }

        $query = array_merge($this->getDefaultQuery(), $query);
        $headers = array_merge($this->getDefaultHeaders(), $headers);

        return $this->client->sendAsync($method, $uri, $body, $query, $headers, $options)->then(
            function (ResponseInterface $response) {
                $this->lastResponse = $response;

                $this->validateResponse($this->lastResponse);

                return $this->lastResponse;
            }
        );
    }
1184465
private function connection($url, $body, $type, $method)
    {
        if ($type === 'json') {
            $mine = 'application/json';
        } else {
            $mine = 'application/xml';
        }
        if (function_exists('curl_init')) {
            $header = array(
                'Accept:' . $mine,
                'Content-Type:' . $mine . ';charset=utf-8',
                'Authorization:' . $this->getAuthorization(),
            );
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
            if ($method === 'post') {
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
            }
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            $result = curl_exec($ch);
            curl_close($ch);
        } else {
            $opts = array();
            $opts['http'] = array();
            $headers = array(
                'method' => strtoupper($method),
            );
            $headers[] = 'Accept:' . $mine;
            $headers['header'] = array();
            $headers['header'][] = 'Authorization: ' . $this->getAuthorization();
            $headers['header'][] = 'Content-Type:' . $mine . ';charset=utf-8';

            if (!empty($body)) {
                $headers['header'][] = 'Content-Length:' . strlen($body);
                $headers['content'] = $body;
            }

            $opts['http'] = $headers;
            $result = file_get_contents($url, false, stream_context_create($opts));
        }

        return $result;
    }
624470
protected function query($uri, array $params = [], $method = self::METHOD_POST)
    {
        $request = new Request($method, $uri, [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Token ' . $this->token,
            'X-Secret'      => $this->secret,
        ], 0 < count($params) ? json_encode($params) : null);

        $response = $this->httpClient->send($request, $this->httpOptions);

        $result = json_decode($response->getBody(), true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new RuntimeException('Error parsing response: ' . json_last_error_msg());
        }

        if (empty($result)) {
            throw new RuntimeException('Empty result');
        }

        return array_shift($result);
    }
952173
public function request($method, $url, $data = null)
    {
        $url = (string)$url;
        $data = array('$data' => $data);

        if (!$this->cache && $this->params['cache']) {
            $client_id = isset($this->params['route']['client'])
                ? $this->params['route']['client']
                : $this->params['client_id'];
            $this->cache = new Cache($client_id, $this->params['cache']);
        }

        try {
            if (!$this->server->connected) {
                if ($this->params['proxy']) {
                    $data = $this->request_proxy_data($data);
                }
                if (!$this->authed) {
                    $data['$client'] = isset($this->params['route']['client'])
                        ? $this->params['route']['client']
                        : $this->params['client_id'];
                    // Perform basic auth by default for secure/non-route based requests
                    if (!isset($this->server->options['clear']) && !isset($this->params['route']['client'])) {
                        $data['$key'] = $this->params['client_key'];
                        if ($this->cache) {
                            $data['$cached'] = $this->cache->get_versions();
                        }
                        if ($this->params['session']) {
                            $data['$session'] = $this->params['session'];
                        }
                    }
                }
                $this->server->connect();
            }
            $result = $this->server->request($method, $url, $data);
        } catch (NetworkException $e) {
            $this->request_rescue($e);
            $result = $this->server->request($method, $url, $data);
        }

        if (isset($result['$auth'])) {
            if (isset($result['$end'])) {
                // Connection ended, retry
                return $this->request($method, $url, $data['$data']);
            } else {
                $result = $this->auth($result['$auth']);
            }
        }

        return $this->response($method, $url, $data, $result);
    }
847963
public function fetch($query, $parameters = array())
    {
        try {
            $sth = $this->query($query, $parameters);
            if ($sth === false) {
                return false;
            }
            return $sth->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            throw new DbException("Error query: " . $e->getMessage());
        }
    }
977733
public function request(string $url, string $method = Request::METHOD_GET, array $postFields = [],
                            string $apiUrl = null): array
    {
        /** Building url */
        if (null === $apiUrl) {
            $apiUrl = $this->getApiUrl();
        }
        $url   = $apiUrl . $url;
        $query = [];

        /**
         * OAuth2 Key/Secret authentication
         *
         * @see https://developer.github.com/v3/#oauth2-keysecret
         */
        if (null !== $this->getClientId() && null !== $this->getClientSecret()) {
            $query['client_id']     = $this->getClientId();
            $query['client_secret'] = $this->getClientSecret();
        } /**
         * Basic authentication via OAuth2 Token (sent as a parameter)
         *
         * @see https://developer.github.com/v3/#oauth2-token-sent-as-a-parameter
         */ else if ($this->getAuthentication() === self::OAUTH2_PARAMETERS_AUTH) {
            $query['access_token'] = $this->getToken();
        }

        /**
         * Pagination
         * Requests that return multiple items will be paginated to 30 items by default.
         * You can specify further pages with the ?page parameter.
         * For some resources, you can also set a custom page size up to 100 with the ?per_page parameter.
         * Note that for technical reasons not all endpoints respect the ?per_page parameter,
         *
         * @see https://developer.github.com/v3/#pagination
         */
        if (null !== $this->getPagination()) {
            if (null !== $this->getPagination()->getPage()) {
                $query['page'] = $this->getPagination()->getPage();
            }
            if (null !== $this->getPagination()->getLimit()) {
                $query['per_page'] = $this->getPagination()->getLimit();
            }
        }

        /**
         * Add URL-encoded query string parameters
         */
        if (!empty($query)) {
            $url .= (strstr($url, '?') !== false ? '&' : '?');
            $url .= http_build_query($query);
        }

        /** Call curl */
        $curl = new CurlClient();
        $curl->setOption([
            CURLOPT_USERAGENT      => self::USER_AGENT,
            CURLOPT_TIMEOUT        => $this->getTimeout(),
            CURLOPT_HEADER         => false, // Use $client->getHeaders() to get full header
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTPHEADER     => [
                'Accept: ' . $this->getAccept(),
                'Content-Type: ' . $this->getContentType()
            ],
            CURLOPT_URL            => $url
        ]);

        /**
         * Basic authentication via username and Password
         *
         * @see https://developer.github.com/v3/auth/#via-username-and-password
         */
        if (!empty($this->getHttpAuth())) {
            if (!isset($this->getHttpAuth()['password']) || empty($this->getHttpAuth()['password'])) {
                $curl->setOption([
                    CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
                    CURLOPT_USERPWD  => $this->getHttpAuth()['username']
                ]);
            } else {
                $curl->setOption([
                    CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
                    CURLOPT_USERPWD  => sprintf('%s:%s', $this->getHttpAuth()['username'],
                        $this->getHttpAuth()['password'])
                ]);
            }
        }

        if (!empty($this->getToken()) && $this->getAuthentication() !== self::OAUTH2_PARAMETERS_AUTH) {
            /**
             * Basic authentication via OAuth token
             *
             * @see https://developer.github.com/v3/auth/#via-oauth-tokens
             **/
            if ($this->getAuthentication() === self::OAUTH_AUTH) {
                $curl->setOption([
                    CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
                    CURLOPT_USERPWD  => sprintf('%s:x-oauth-basic', $this->getToken())
                ]);
            } /**
             * Basic authentication via OAuth2 Token (sent in a header)
             *
             * @see https://developer.github.com/v3/#oauth2-token-sent-in-a-header
             */ else if ($this->getAuthentication() === self::OAUTH2_HEADER_AUTH) {
                $curl->setOption([
                    CURLOPT_HTTPAUTH   => CURLAUTH_BASIC,
                    CURLOPT_HTTPHEADER => [sprintf('Authorization: token %s', $this->getToken())]
                ]);
            }
        }

        /** Methods */
        switch ($method) {
            /** @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7 */
            case Request::METHOD_DELETE:
                /** @see http://tools.ietf.org/html/rfc5789 */
            case Request::METHOD_PATCH:
                $curl->setOption([
                    CURLOPT_CUSTOMREQUEST => $method,
                    CURLOPT_POST          => true,
                    CURLOPT_POSTFIELDS    => json_encode(array_filter($postFields))
                ]);
                break;

            /** @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3 */
            case Request::METHOD_GET:
                $curl->setOption(CURLOPT_HTTPGET, true);
                break;

            /** @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 */
            case Request::METHOD_HEAD:
                $curl->setOption([
                    CURLOPT_CUSTOMREQUEST => $method,
                    CURLOPT_NOBODY        => true
                ]);
                break;

            /** @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5 */
            case Request::METHOD_POST:
                $curl->setOption([
                    CURLOPT_POST       => true,
                    CURLOPT_POSTFIELDS => json_encode(array_filter($postFields))
                ]);
                break;

            /** @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6 */
            case Request::METHOD_PUT:
                $curl->setOption([
                    CURLOPT_CUSTOMREQUEST => $method,
                    CURLOPT_PUT           => true,
                    CURLOPT_HTTPHEADER    => [
                        'X-HTTP-Method-Override: PUT',
                        'Content-type: application/x-www-form-urlencoded'
                    ]
                ]);
                break;

            default:
                break;
        }

        $curl->success(function (CurlClient $instance) {
            $this->headers = $instance->getHeaders();
            $this->success = $instance->getResponse();
            $data          = json_decode($this->success, true);
            if (JSON_ERROR_NONE === json_last_error()) {
                $this->success = $data;
            }
        });
        $curl->error(function (CurlClient $instance) {
            $this->headers = $instance->getHeaders();
            $this->failure = $instance->getResponse();
            $data          = json_decode($this->failure, true);
            if (JSON_ERROR_NONE === json_last_error()) {
                $this->failure = $data;
            }
        });
        $curl->perform();

        return (array)($this->success ?? $this->failure);
    }
1364722
private function request($method, $uri, $body = array())
    {
        try {
            $res = $this->client->request($method, $uri, $body);
            return json_decode($res->getBody());
        } catch(RequestException $e){
            $res = VariableUtil::json2Array(
                json_decode($e->getResponse()->getBody()->getContents())[0]
            );
            /*
             * If the session expired, then we must request a new token with the
             * refresh token.
             */
            if(isset($res['errorCode']) && $res['errorCode'] == 'INVALID_SESSION_ID'){
                $this->refreshToken($method, $uri, $body);
            } else {
                throw new ExternalApiException($e->getMessage(), $e->getCode(), $e);
            }
        }
    }
89982
public function post(string $query, ?string $body = null): ResponseInterface
    {
        $options = [
            'headers' => $this->getAuthorizationHeader(),
        ];

        if ($body) {
            $options['body'] = $body;
        }

        return $this->client->request('post', $this->buildQuery($query), $options);
    }