protected function doRequest($url, $ctx, &$responseHeaders, $methodName) {
        // make a real request
        $result = @file_get_contents($url, null, $ctx);
        if (!$result) {
            throw new \Exception('HTTP request failed', HttpException::REQUEST_FAILED);
        }

        // catch headers
        $responseHeaders = $this->parseHeaders($http_response_header);

        foreach (array('Content-Encoding', 'content-encoding') as $header) {
            if (isset($responseHeaders[$header])) {
                if (strtolower($responseHeaders[$header]) == 'gzip') {
                    $result = gzinflate(substr($result, 10, -8));
                    break;
                }
            }
        }

        $logger = $this->getLogger();
        $logger->debug('Response headers: ' . var_export($responseHeaders, true));
        $logger->debug('Response body: ' . $result);

        // completely failed
        if (!$result && $methodName != 'HEAD') {
            throw new \Exception('No response from server');
        } else if ($responseHeaders['Code'] < 200 || $responseHeaders['Code'] >= 400) {
            // server returned error code

            // decode if it's JSON
            if ($responseHeaders['Content-Type'] == 'application/json') {
                $parsedResult = @json_decode($result, true);
            }

            // pass responses (not) decoded to the adequate exception parameters
            if (isset($parsedResult) && is_array($parsedResult)) {
                $description = $parsedResult['error'];
                if (isset($parsedResult['error_description'])) {
                    $description = $parsedResult['error_description'];
                }
            } else {
                $description = 'Server error occurred';
            }

            throw new HttpException(
                $description,
                $responseHeaders['Code'],
                null,
                $methodName,
                null,
                array(),
                array(),
                array(),
                $result,
                $responseHeaders
            );
        }

        return $result;
    }