Wraps HTTPConnection.request. On exception it calls exception_fn
        with the exception object. If exception_fn is None, it re-raises the
        exception. If notimeout is True, create a new connection (regardless of
        self.reuseconnection setting) that uses the global default timeout for
        sockets (usually None).

def request(self,
                method,
                path,
                body=None,
                headers={},
                exception_fn=None,
                notimeout=False,
                verify=True):
        """Wraps HTTPConnection.request. On exception it calls exception_fn
        with the exception object. If exception_fn is None, it re-raises the
        exception. If notimeout is True, create a new connection (regardless of
        self.reuseconnection setting) that uses the global default timeout for
        sockets (usually None)."""
        # This needs to be done first because self.session may be None
        if not self.reuseconnection or notimeout:
            self.close()
            self.session = Session()

        allheaders = headers
        allheaders.update(self.session.headers)

        try:
            if self.curldebug:
                # output request as a curl call
                def escape(s):
                    """escape single quotes for bash"""
                    return s.replace("'", "'\\''")

                self.log.debug(
                    "curl '{1}{2}' -X {3} -m {4} {5} {6}".format(
                        'https' if self.https else 'http',
                        self.host,
                        path,
                        method,
                        self.httptimeout,
                        ' '.join(['-H \'{0}: {1}\''.format(escape(h), escape(allheaders[h]))
                                  for h in allheaders]),
                        '' if body is None else '-d \'' + escape(body) + '\''))
            else:
                self.log.debug("%s %s\nHost: %s\nHeaders: %s" % (
                    method,
                    path,
                    self.host,
                    allheaders))
                if body is not None:
                    self.log.debug("Body: %s" % body)
            URI = self.host + path
            prepped = self.session.prepare_request(
                Request(method, URI, data=body, headers=headers)
            )

            response = self.session.send(
                prepped,
                verify=verify,
                timeout=None if notimeout else self.httptimeout
            )
            return response.text, response

        except Exception:
            self.close()
            ex = sys.exc_info()[1]
            if exception_fn is not None:
                exception_fn(ex)
            else:
                raise ex