Sends an HTTP request.

        This constructs a full URL, encodes and decodes HTTP bodies, and
        handles invalid responses in a pythonic way.

        @type method: string
        @param method: HTTP method to use
        @type path: string
        @param path: HTTP URL path
        @type query: list of two-tuples
        @param query: query arguments to pass to urllib.urlencode
        @type content: str or None
        @param content: HTTP body content

        @rtype: object
        @return: JSON-Decoded response

        @raises GanetiApiError: If an invalid response is returned

def request(self, method, path, query=None, content=None):
        """
        Sends an HTTP request.

        This constructs a full URL, encodes and decodes HTTP bodies, and
        handles invalid responses in a pythonic way.

        @type method: string
        @param method: HTTP method to use
        @type path: string
        @param path: HTTP URL path
        @type query: list of two-tuples
        @param query: query arguments to pass to urllib.urlencode
        @type content: str or None
        @param content: HTTP body content

        @rtype: object
        @return: JSON-Decoded response

        @raises GanetiApiError: If an invalid response is returned
        """

        kwargs = {
            "headers": headers,
            "timeout": self.timeout,
            "verify": False,
        }

        if self.username and self.password:
            kwargs["auth"] = self.username, self.password

        if content is not None:
            kwargs["data"] = self._json_encoder.encode(content)

        if query:
            prepare_query(query)
            kwargs["params"] = query

        url = self._base_url + path

        # print "Sending request to %s %s" % (url, kwargs)

        try:
            r = requests.request(method, url, **kwargs)
        except requests.ConnectionError:
            raise GanetiApiError("Couldn't connect to %s" % self._base_url)
        except requests.Timeout:
            raise GanetiApiError("Timed out connecting to %s" %
                                 self._base_url)

        if r.status_code != requests.codes.ok:
            raise NotOkayError(str(r.status_code), code=r.status_code)

        if r.content:
            return json.loads(r.content)
        else:
            return None