def from_response(response, method, url):
"""Returns an instance of :class:`HttpError` or subclass based on response.
:param response: instance of `requests.Response` class
:param method: HTTP method used for request
:param url: URL used for request
"""
req_id = response.headers.get('X-openstack-request-id')
# NOTE(hdd) true for older versions of nova and cinder
if not req_id:
req_id = response.headers.get('X-compute-request-id')
kwargs = {
'http_status': response.status_code,
'response': response,
'method': method,
'url': url,
'request_id': req_id
}
if 'retry_after' in response.headers:
kwargs['retry_after'] = response.headers['retry_after']
content_type = response.headers.get('Content-Type', "")
if content_type.startswith('application/json'):
try:
body = response.json()
except ValueError:
pass
else:
if isinstance(body, dict):
error = body.get(list(body)[0])
if isinstance(error, dict):
kwargs['message'] = (error.get('message') or
error.get('faultstring'))
kwargs['details'] = (error.get('details') or
six.text_type(body))
elif content_type.startswith("text/"):
kwargs['details'] = getattr(response, 'text', '')
try:
cls = _code_map[response.status_code]
except KeyError:
# 5XX status codes are server errors
if response.status_code >= http_client.INTERNAL_SERVER_ERROR:
cls = HttpServerError
# 4XX status codes are client request errors
elif (http_client.BAD_REQUEST <= response.status_code <
http_client.INTERNAL_SERVER_ERROR):
cls = HTTPClientError
else:
cls = HttpError
return cls(**kwargs)
评论列表
文章目录