Exemplo n.º 1
0
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
        kwargs['headers'].setdefault('User-Agent', USER_AGENT)
        if self.auth_token:
            kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        try:
            conn_url = self._make_connection_url(url)
            conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = ("Error finding address for %(url)s: %(e)s" %
                       dict(url=url, e=e))
            raise exceptions.EndpointNotFound(message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = ("Error communicating with %(endpoint)s %(e)s" %
                       dict(endpoint=endpoint, e=e))
            raise exceptions.ConnectionRefused(message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        body_str = None
        if resp.getheader('content-type', None) != 'application/octet-stream':
            body_str = ''.join([chunk for chunk in body_iter])
            self.log_http_response(resp, body_str)
            body_iter = six.StringIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.warn("Request returned failure status.")
            error_json = self._extract_error_json(body_str)
            raise exceptions.from_response(resp, error_json.get('faultstring'),
                                           error_json.get('debuginfo'), method,
                                           url)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp['location'], method, **kwargs)
        elif resp.status == 300:
            raise exceptions.from_response(resp, method=method, url=url)

        return resp, body_iter
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
        kwargs['headers'].setdefault('User-Agent', USER_AGENT)
        if self.api_version:
            version_string = 'container-infra %s' % self.api_version
            kwargs['headers'].setdefault('OpenStack-API-Version',
                                         version_string)
        if self.auth_token:
            kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        try:
            conn_url = self._make_connection_url(url)
            conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = ("Error finding address for %(url)s: %(e)s" %
                       dict(url=url, e=e))
            raise exceptions.EndpointNotFound(message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = ("Error communicating with %(endpoint)s %(e)s" %
                       dict(endpoint=endpoint, e=e))
            raise exceptions.ConnectionRefused(message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        body_str = None
        if resp.getheader('content-type', None) != 'application/octet-stream':
            # decoding byte to string is necessary for Python 3.4 compatibility
            # this issues has not been found with Python 3.4 unit tests
            # because the test creates a fake http response of type str
            # the if statement satisfies test (str) and real (bytes) behavior
            body_list = [
                chunk.decode("utf-8") if isinstance(chunk, bytes) else chunk
                for chunk in body_iter
            ]
            body_str = ''.join(body_list)
            self.log_http_response(resp, body_str)
            body_iter = six.StringIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.warning("Request returned failure status.")
            error_json = _extract_error_json(body_str)
            raise exceptions.from_response(resp, error_json.get('faultstring'),
                                           error_json.get('debuginfo'), method,
                                           url)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp['location'], method, **kwargs)
        elif resp.status == 300:
            raise exceptions.from_response(resp, method=method, url=url)

        return resp, body_iter