Execute an HTTP request and return a dict containing the response
        and the response status code.

        Keyword arguments:
        url -- The path to execute the result against, not including the API
               version or project ID, with no leading /. Required.
        method -- The HTTP method to use. Required.
        body -- A string or file object to send as the body of the request.
                Defaults to an empty string.
        headers -- HTTP Headers to send with the request. Can overwrite the
                   defaults. Defaults to {}.
        retry -- Whether exponential backoff should be employed. Defaults
                 to True.

def request(self, url, method, body="", headers={}, retry=True):
        """Execute an HTTP request and return a dict containing the response
        and the response status code.

        Keyword arguments:
        url -- The path to execute the result against, not including the API
               version or project ID, with no leading /. Required.
        method -- The HTTP method to use. Required.
        body -- A string or file object to send as the body of the request.
                Defaults to an empty string.
        headers -- HTTP Headers to send with the request. Can overwrite the
                   defaults. Defaults to {}.
        retry -- Whether exponential backoff should be employed. Defaults
                 to True.
        """
        if headers:
            headers = dict(list(headers.items()) + list(self.headers.items()))
        else:
            headers = self.headers

        if not sys.version_info >= (3,) and headers:
            headers = dict((k.encode('ascii') if isinstance(k, unicode) else k,
                            v.encode('ascii') if isinstance(v, unicode) else v)
                           for k, v in headers.items())

        url = self.base_url + url
        if not sys.version_info >= (3,):
            if isinstance(url, unicode):
                url = url.encode('ascii')

        r = self._doRequest(url, method, body, headers)

        retry_http_codes = [503, 504]
        if r.status_code in retry_http_codes and retry:
            tries = 5
            delay = .5
            backoff = 2
            while r.status_code in retry_http_codes and tries > 0:
                tries -= 1
                time.sleep(delay)
                delay *= backoff
                r = self._doRequest(url, method, body, headers)

        r.raise_for_status()

        result = {}
        contentType = r.headers["Content-Type"]
        if contentType is None:
            contentType = "text/plain"
        else:
            contentType = contentType.split(";")[0]
        if contentType.lower() == "application/json":
            try:
                result["body"] = json.loads(r.text)
            except:
                result["body"] = r.text
        else:
            result["body"] = r.text
        result["status"] = r.status_code
        result["resp"] = r
        result["content-type"] = contentType
        return result