def request(self, url, method, json=None, original_ip=None, user_agent=None, redirect=None, endpoint_filter=None, raise_exc=True, log=True, microversion=None, endpoint_override=None, connect_retries=0, allow=None, client_name=None, client_version=None, **kwargs): headers = kwargs.setdefault('headers', dict()) if microversion: self._set_microversion_headers(headers, microversion, None, endpoint_filter) if self._securitytoken: headers.setdefault("X-Security-Token", self._securitytoken) if not urllib.parse.urlparse(url).netloc: if endpoint_override: base_url = endpoint_override % {"project_id": self.project_id} elif endpoint_filter: base_url = self.get_endpoint(interface=endpoint_filter.interface, service_type=endpoint_filter.service_type) if not urllib.parse.urlparse(base_url).netloc: raise exceptions.EndpointNotFound() url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/')) headers.setdefault("Host", urllib.parse.urlparse(url).netloc) if self.cert: kwargs.setdefault('cert', self.cert) if self.timeout is not None: kwargs.setdefault('timeout', self.timeout) if user_agent: headers['User-Agent'] = user_agent elif self.user_agent: user_agent = headers.setdefault('User-Agent', self.user_agent) else: # Per RFC 7231 Section 5.5.3, identifiers in a user-agent should be # ordered by decreasing significance. If a user sets their product # that value will be used. Otherwise we attempt to derive a useful # product value. The value will be prepended it to the KSA version, # requests version, and then the Python version. agent = [] if self.app_name and self.app_version: agent.append('%s/%s' % (self.app_name, self.app_version)) elif self.app_name: agent.append(self.app_name) if client_name and client_version: agent.append('%s/%s' % (client_name, client_version)) elif client_name: agent.append(client_name) for additional in self.additional_user_agent: agent.append('%s/%s' % additional) if not agent: # NOTE(jamielennox): determine_user_agent will return an empty # string on failure so checking for None will ensure it is only # called once even on failure. if self._determined_user_agent is None: self._determined_user_agent = _determine_user_agent() if self._determined_user_agent: agent.append(self._determined_user_agent) agent.append(DEFAULT_USER_AGENT) user_agent = headers.setdefault('User-Agent', ' '.join(agent)) if self.original_ip: headers.setdefault('Forwarded', 'for=%s;by=%s' % (self.original_ip, user_agent)) if json is not None: kwargs['data'] = self._json.encode(json) # surpport maas,map_reduce when without request body headers.setdefault('Content-Type', 'application/json') if self.domain_id: headers.setdefault('X-Domain-Id', self.domain_id) # surpport sub-project id for some service the endpoint contain project id elif self.project_id: headers.setdefault('X-Project-Id', self.project_id) if self.additional_headers: for k, v in self.additional_headers.items(): headers.setdefault(k, v) kwargs.setdefault('verify', self.verify) # if requests_auth: # kwargs['auth'] = requests_auth # Query parameters that are included in the url string will # be logged properly, but those sent in the `params` parameter # (which the requests library handles) need to be explicitly # picked out so they can be included in the URL that gets loggged. query_params = kwargs.get('params', dict()) headers.setdefault("X-Sdk-Date", datetime.datetime.strftime(datetime.datetime.utcnow(), "%Y%m%dT%H%M%SZ")) signedstring = self.signer.signature(method=method, url=url, headers=headers, svr=endpoint_filter.service_type if endpoint_filter else '', params=query_params, data=kwargs.get("data", None)) # print(signedstring) headers.setdefault("Authorization", signedstring) if log: self._http_log_request(url, method=method, data=kwargs.get('data'), headers=headers, query_params=query_params, logger=_logger) # Force disable requests redirect handling. We will manage this below. kwargs['allow_redirects'] = False if redirect is None: redirect = self.redirect send = functools.partial(self._send_request, url, method, redirect, log, _logger, connect_retries) resp = send(**kwargs) # log callee and caller request-id for each api call if log: # service_name should be fetched from endpoint_filter if it is not # present then use service_type as service_name. service_name = None if endpoint_filter: service_name = endpoint_filter.get('service_name') if not service_name: service_name = endpoint_filter.get('service_type') # Nova uses 'x-compute-request-id' and other services like # Glance, Cinder etc are using 'x-openstack-request-id' to store # request-id in the header request_id = (resp.headers.get('x-openstack-request-id') or resp.headers.get('x-compute-request-id')) if request_id: _logger.debug('%(method)s call to %(service_name)s for ' '%(url)s used request id ' '%(response_request_id)s', {'method': resp.request.method, 'service_name': service_name, 'url': resp.url, 'response_request_id': request_id}) if raise_exc and resp.status_code >= 400: _logger.debug('Request returned failure status: %s', resp.status_code) raise exceptions.from_response(resp, method, url) return resp
def request(self, url, method, json=None, original_ip=None, user_agent=None, redirect=None, endpoint_filter=None, raise_exc=True, log=True, microversion=None, endpoint_override=None, connect_retries=0, allow=None, client_name=None, client_version=None, **kwargs): self._determined_user_agent = None headers = kwargs.setdefault('headers', dict()) auth_headers = self.get_auth_headers() if auth_headers is None: msg = 'No valid authentication is available' raise exceptions.AuthorizationFailure(msg) headers.update(auth_headers) base_url = "" if not urllib.parse.urlparse(url).netloc: if endpoint_override: base_url = endpoint_override # base_url = endpoint_override % {"project_id": self.project_id} elif endpoint_filter: base_url = self.get_endpoint( interface=endpoint_filter.interface, service_type=endpoint_filter.service_type) if not urllib.parse.urlparse(base_url).netloc: raise exceptions.EndpointNotFound() url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/')) headers.setdefault("Host", urllib.parse.urlparse(url).netloc) if self.cert: kwargs.setdefault('cert', self.cert) if self.timeout is not None: kwargs.setdefault('timeout', self.timeout) if user_agent: headers['User-Agent'] = user_agent elif self.user_agent: user_agent = headers.setdefault('User-Agent', self.user_agent) else: agent = [] if self.app_name and self.app_version: agent.append('%s/%s' % (self.app_name, self.app_version)) elif self.app_name: agent.append(self.app_name) if client_name and client_version: agent.append('%s/%s' % (client_name, client_version)) elif client_name: agent.append(client_name) for additional in self.additional_user_agent: agent.append('%s/%s' % additional) if not agent: # NOTE(jamielennox): determine_user_agent will return an empty # string on failure so checking for None will ensure it is only # called once even on failure. if self._determined_user_agent is None: self._determined_user_agent = _determine_user_agent() if self._determined_user_agent: agent.append(self._determined_user_agent) agent.append(DEFAULT_USER_AGENT) user_agent = headers.setdefault('User-Agent', ' '.join(agent)) if self.original_ip: headers.setdefault('Forwarded', 'for=%s;by=%s' % (self.original_ip, user_agent)) if json is not None: kwargs['data'] = self._json.encode(json) headers.setdefault('Content-Type', 'application/json') if self.additional_headers: for k, v in self.additional_headers.items(): headers.setdefault(k, v) kwargs.setdefault('verify', self.verify) # if requests_auth: # kwargs['auth'] = requests_auth # Query parameters that are included in the url string will # be logged properly, but those sent in the `params` parameter # (which the requests library handles) need to be explicitly # picked out so they can be included in the URL that gets loggged. query_params = kwargs.get('params', dict()) if log: self._http_log_request(url, method=method, data=kwargs.get('data'), headers=headers, query_params=query_params, logger=_logger) # Force disable requests redirect handling. We will manage this below. kwargs['allow_redirects'] = False if redirect is None: redirect = self.redirect send = functools.partial(self._send_request, url, method, redirect, log, _logger, connect_retries) resp = send(**kwargs) # log callee and caller request-id for each api call if log: # service_name should be fetched from endpoint_filter if it is not # present then use service_type as service_name. service_name = None if endpoint_filter: service_name = endpoint_filter.get('service_name') if not service_name: service_name = endpoint_filter.get('service_type') # Nova uses 'x-compute-request-id' and other services like # Glance, Cinder etc are using 'x-openstack-request-id' to store # request-id in the header request_id = (resp.headers.get('x-openstack-request-id') or resp.headers.get('x-compute-request-id')) if request_id: _logger.debug( '%(method)s call to %(service_name)s for ' '%(url)s used request id ' '%(response_request_id)s', { 'method': resp.request.method, 'service_name': service_name, 'url': resp.url, 'response_request_id': request_id }) if raise_exc and resp.status_code >= 400: _logger.debug('Request returned failure status: %s', resp.status_code) raise exceptions.from_response(resp, method, url) return resp