def _request(self, method, url, **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 headers = copy.deepcopy(kwargs.pop('headers', {})) if self.identity_headers: for k, v in six.iteritems(self.identity_headers): headers.setdefault(k, v) data = self._set_common_request_kwargs(headers, kwargs) # add identity header to the request if not headers.get('X-Auth-Token'): headers['X-Auth-Token'] = self.auth_token if osprofiler_web: headers.update(osprofiler_web.get_trace_id_headers()) # Note(flaper87): Before letting headers / url fly, # they should be encoded otherwise httplib will # complain. headers = encode_headers(headers) if self.endpoint.endswith("/") or url.startswith("/"): conn_url = "%s%s" % (self.endpoint, url) else: conn_url = "%s/%s" % (self.endpoint, url) self.log_curl_request(method, conn_url, headers, data, kwargs) try: resp = self.session.request(method, conn_url, data=data, headers=headers, **kwargs) except requests.exceptions.Timeout as e: message = ("Error communicating with %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.InvalidEndpoint(message=message) except requests.exceptions.ConnectionError as e: message = ("Error finding address for %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.CommunicationError(message=message) except socket.gaierror as e: message = "Error finding address for %s: %s" % ( self.endpoint_hostname, e) raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = ("Error communicating with %(endpoint)s %(e)s" % {'endpoint': endpoint, 'e': e}) raise exc.CommunicationError(message=message) resp, body_iter = self._handle_response(resp) self.log_http_response(resp) return resp, body_iter
def request(self, url, method, **kwargs): headers = kwargs.pop('headers', {}) kwargs['raise_exc'] = False data = self._set_common_request_kwargs(headers, kwargs) try: resp = super(SessionClient, self).request(url, method, headers=headers, data=data, **kwargs) except ksc_exc.RequestTimeout as e: conn_url = self.get_endpoint(auth=kwargs.get('auth')) conn_url = "%s/%s" % (conn_url.rstrip('/'), url.lstrip('/')) message = ("Error communicating with %(url)s %(e)s" % dict(url=conn_url, e=e)) raise exc.InvalidEndpoint(message=message) except ksc_exc.ConnectionRefused as e: conn_url = self.get_endpoint(auth=kwargs.get('auth')) conn_url = "%s/%s" % (conn_url.rstrip('/'), url.lstrip('/')) message = ("Error finding address for %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.CommunicationError(message=message) return self._handle_response(resp)
def get_connection(self): _class = self.connection_class try: return _class(self.endpoint_hostname, self.endpoint_port, **self.connection_kwargs) except http_client.InvalidURL: raise exc.InvalidEndpoint()
def request(self, url, method, **kwargs): headers = kwargs.pop('headers', {}) if self.global_request_id: headers.setdefault(REQ_ID_HEADER, self.global_request_id) kwargs['raise_exc'] = False data = self._set_common_request_kwargs(headers, kwargs) try: # NOTE(pumaranikar): To avoid bug #1641239, no modification of # headers should be allowed after encode_headers() is called. resp = super(SessionClient, self).request(url, method, headers=encode_headers(headers), data=data, **kwargs) except ksa_exc.ConnectTimeout as e: conn_url = self.get_endpoint(auth=kwargs.get('auth')) conn_url = "%s/%s" % (conn_url.rstrip('/'), url.lstrip('/')) message = ("Error communicating with %(url)s %(e)s" % dict(url=conn_url, e=e)) raise exc.InvalidEndpoint(message=message) except ksa_exc.ConnectFailure as e: conn_url = self.get_endpoint(auth=kwargs.get('auth')) conn_url = "%s/%s" % (conn_url.rstrip('/'), url.lstrip('/')) message = ("Error finding address for %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.CommunicationError(message=message) return self._handle_response(resp)
def request(self, url, method, **kwargs): headers = kwargs.setdefault('headers', {}) content_type = headers.get('Content-Type', 'application/octet-stream') data = kwargs.pop("data", None) if data is not None and not isinstance(data, six.string_types): try: data = json.dumps(data) content_type = 'application/json' except TypeError: # Here we assume it's a file-like object and we'll chunk it data = chunk_body(data) headers['Content-Type'] = content_type kwargs['data'] = data kwargs['raise_exc'] = False kwargs['stream'] = content_type == 'application/octet-stream' try: resp = super(SessionClient, self).request(url, method, **kwargs) except ksc_exc.RequestTimeout as e: message = ("Error communicating with %(endpoint)s %(e)s" % dict(url=conn_url, e=e)) raise exc.InvalidEndpoint(message=message) except ksc_exc.ConnectionRefused as e: conn_url = self.get_endpoint(auth=kwargs.get('auth')) message = ("Error finding address for %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.CommunicationError(message=message) if not resp.ok: LOG.debug("Request returned failure status %s." % resp.status_code) raise exc.from_response(resp, resp.content) elif resp.status_code == requests.codes.MULTIPLE_CHOICES: raise exc.from_response(resp) content_type = resp.headers.get('Content-Type') # Read body into string if it isn't obviously image data if content_type == 'application/octet-stream': # Do not read all response in memory when downloading an image. body_iter = _close_after_stream(resp, CHUNKSIZE) else: content = resp.content if content_type and content_type.startswith('application/json'): # Let's use requests json method, it should take care of # response encoding body_iter = resp.json() else: body_iter = six.StringIO(content) try: body_iter = json.loads(''.join([c for c in body_iter])) except ValueError: body_iter = None 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.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 = os.path.normpath('%s/%s' % (self.endpoint_path, url)) conn.request(method, conn_url, **kwargs) resp = conn.getresponse() except socket.gaierror as e: message = "Error finding address for %(url)s: %(e)s" % locals() raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = "Error communicating with %(endpoint)s %(e)s" % locals() raise exc.CommunicationError(message=message) body_iter = ResponseBodyIterator(resp) # Read body into string if it isn't obviously image data 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 = StringIO.StringIO(body_str) else: self.log_http_response(resp) if 400 <= resp.status < 600: LOG.error("Request returned failure status.") raise exc.from_response(resp) 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 exc.from_response(resp) 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.auth_token: kwargs['headers'].setdefault('X-Auth-Token', self.auth_token) if self.identity_headers: for k, v in self.identity_headers.iteritems(): kwargs['headers'].setdefault(k, v) self.log_curl_request(method, url, kwargs) conn = self.get_connection() # Note(flaper87): Before letting headers / url fly, # they should be encoded otherwise httplib will # complain. If we decide to rely on python-request # this wont be necessary anymore. kwargs['headers'] = self.encode_headers(kwargs['headers']) try: if self.endpoint_path: # NOTE(yuyangbj): this method _http_request could either be # called by API layer, or be called recursively with # redirection. For example, url would be '/v1/images/detail' # from API layer, but url would be 'https://example.com:92/ # v1/images/detail' from recursion. # See bug #1230032 and bug #1208618. if url is not None: all_parts = urlparse.urlparse(url) if not (all_parts.scheme and all_parts.netloc): norm_parse = posixpath.normpath url = norm_parse('/'.join([self.endpoint_path, url])) else: url = self.endpoint_path conn_url = urlparse.urlsplit(url).geturl() # Note(flaper87): Ditto, headers / url # encoding to make httplib happy. conn_url = strutils.safe_encode(conn_url) if kwargs['headers'].get('Transfer-Encoding') == 'chunked': conn.putrequest(method, conn_url) for header, value in kwargs['headers'].items(): conn.putheader(header, value) conn.endheaders() chunk = kwargs['body'].read(CHUNKSIZE) # Chunk it, baby... while chunk: conn.send('%x\r\n%s\r\n' % (len(chunk), chunk)) chunk = kwargs['body'].read(CHUNKSIZE) conn.send('0\r\n\r\n') else: conn.request(method, conn_url, **kwargs) resp = conn.getresponse() except socket.gaierror as e: message = "Error finding address for %s: %s" % ( self.endpoint_hostname, e) raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = ("Error communicating with %(endpoint)s %(e)s" % { 'endpoint': endpoint, 'e': e }) raise exc.CommunicationError(message=message) body_iter = ResponseBodyIterator(resp) # Read body into string if it isn't obviously image data 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 = StringIO.StringIO(body_str) else: self.log_http_response(resp) if 400 <= resp.status < 600: LOG.error("Request returned failure status.") raise exc.from_response(resp, body_str) elif resp.status in (301, 302, 305): # Redirected. Reissue the request to the new location. return self._http_request(resp.getheader('location', None), method, **kwargs) elif resp.status == 300: raise exc.from_response(resp) return resp, body_iter
def _request(self, method, url, **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 headers = kwargs.pop("headers", {}) headers = headers and copy.deepcopy(headers) or {} # Default Content-Type is octet-stream content_type = headers.get('Content-Type', 'application/octet-stream') def chunk_body(body): chunk = body while chunk: chunk = body.read(CHUNKSIZE) yield chunk data = kwargs.pop("data", None) if data is not None and not isinstance(data, six.string_types): try: data = json.dumps(data) content_type = 'application/json' except TypeError: # Here we assume it's # a file-like object # and we'll chunk it data = chunk_body(data) headers['Content-Type'] = content_type # Note(flaper87): Before letting headers / url fly, # they should be encoded otherwise httplib will # complain. headers = self.encode_headers(headers) try: conn_url = "%s/%s" % (self.endpoint, url) self.log_curl_request(method, conn_url, headers, data, kwargs) resp = self.session.request(method, conn_url, data=data, stream=True, headers=headers, **kwargs) except requests.exceptions.Timeout as e: message = ("Error communicating with %(endpoint)s %(e)s" % dict(url=conn_url, e=e)) raise exc.InvalidEndpoint(message=message) except requests.exceptions.ConnectionError as e: message = ("Error finding address for %(url)s: %(e)s" % dict(url=conn_url, e=e)) raise exc.CommunicationError(message=message) except socket.gaierror as e: message = "Error finding address for %s: %s" % ( self.endpoint_hostname, e) raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = ("Error communicating with %(endpoint)s %(e)s" % { 'endpoint': endpoint, 'e': e }) raise exc.CommunicationError(message=message) if not resp.ok: LOG.error("Request returned failure status %s." % resp.status_code) raise exc.from_response(resp, resp.content) elif resp.status_code == requests.codes.MULTIPLE_CHOICES: raise exc.from_response(resp) content_type = resp.headers.get('Content-Type') # Read body into string if it isn't obviously image data if content_type == 'application/octet-stream': # Do not read all response in memory when # downloading an image. body_iter = resp.iter_content(chunk_size=CHUNKSIZE) self.log_http_response(resp) else: content = resp.content self.log_http_response(resp, content) if content_type and content_type.startswith('application/json'): # Let's use requests json method, # it should take care of response # encoding body_iter = resp.json() else: body_iter = six.StringIO(content) 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.auth_token: kwargs['headers'].setdefault('X-Auth-Token', self.auth_token) self.log_curl_request(method, url, kwargs) conn = self.get_connection() # Note(flaper87): Before letting headers / url fly, # they should be encoded otherwise httplib will # complain. If we decide to rely on python-request # this wont be necessary anymore. kwargs['headers'] = self.encode_headers(kwargs['headers']) try: if self.endpoint_path: url = '%s/%s' % (self.endpoint_path, url) conn_url = posixpath.normpath(url) # Note(flaper87): Ditto, headers / url # encoding to make httplib happy. conn_url = strutils.safe_encode(conn_url) if kwargs['headers'].get('Transfer-Encoding') == 'chunked': conn.putrequest(method, conn_url) for header, value in kwargs['headers'].items(): conn.putheader(header, value) conn.endheaders() chunk = kwargs['body'].read(CHUNKSIZE) # Chunk it, baby... while chunk: conn.send('%x\r\n%s\r\n' % (len(chunk), chunk)) chunk = kwargs['body'].read(CHUNKSIZE) conn.send('0\r\n\r\n') else: conn.request(method, conn_url, **kwargs) resp = conn.getresponse() except socket.gaierror as e: message = "Error finding address for %s: %s" % ( self.endpoint_hostname, e) raise exc.InvalidEndpoint(message=message) except (socket.error, socket.timeout) as e: endpoint = self.endpoint message = "Error communicating with %(endpoint)s %(e)s" % locals() raise exc.CommunicationError(message=message) body_iter = ResponseBodyIterator(resp) # Read body into string if it isn't obviously image data 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 = StringIO.StringIO(body_str) else: self.log_http_response(resp) if 400 <= resp.status < 600: LOG.error("Request returned failure status.") raise exc.from_response(resp, body_str) 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 exc.from_response(resp) return resp, body_iter