def METHOD_NAME(self, method, url, params=None, body=None, timeout=None, ignore=(), headers=None):
    url = self.base_url + url
    if params:
        url = '%s?%s' % (url, urlencode(params or {}))
    start = time.time()
    request = requests.Request(method=method, headers=headers, url=url, data=body)
    prepared_request = self.session.prepare_request(request)
    settings = self.session.merge_environment_settings(prepared_request.url, {}, None, None, None)
    send_kwargs = {'timeout': timeout or self.timeout}
    send_kwargs.update(settings)
    try:
        response = self.session.send(prepared_request, **send_kwargs)
        duration = time.time() - start
        raw_data = response.text
    except Exception as e:
        self.log_request_fail(method, url, prepared_request.path_url, body, time.time() - start, exception=e)
        if isinstance(e, requests.exceptions.SSLError):
            raise SSLError('N/A', str(e), e)
        if isinstance(e, requests.Timeout):
            raise ConnectionTimeout('TIMEOUT', str(e), e)
        raise ConnectionError('N/A', str(e), e)
    # raise errors based on http status codes, let the client handle those if needed
    if not (200 <= response.status_code < 300) and response.status_code not in ignore:
        self.log_request_fail(method, url, response.request.path_url, body, duration, response.status_code, raw_data)
        self._raise_error(response.status_code, raw_data)
    self.log_request_success(method, url, response.request.path_url, body, response.status_code, raw_data, duration)
    return response.status_code, response.headers, raw_data