199 lines
5.9 KiB
Python
199 lines
5.9 KiB
Python
import requests
|
|
from dcos import util
|
|
from dcos.errors import DCOSException
|
|
|
|
logger = util.get_logger(__name__)
|
|
|
|
|
|
def _default_is_success(status_code):
|
|
"""Returns true if the success status is between [200, 300).
|
|
|
|
:param response_status: the http response status
|
|
:type response_status: int
|
|
:returns: True for success status; False otherwise
|
|
:rtype: bool
|
|
"""
|
|
|
|
return status_code >= 200 and status_code < 300
|
|
|
|
|
|
def _default_to_exception(response):
|
|
"""
|
|
:param response: HTTP response object or Exception
|
|
:type response: requests.Response | Exception
|
|
:returns: exception
|
|
:rtype: Exception
|
|
"""
|
|
|
|
if isinstance(response, Exception) and \
|
|
not isinstance(response, requests.exceptions.RequestException):
|
|
return response
|
|
|
|
url = response.request.url
|
|
if isinstance(response, requests.exceptions.ConnectionError):
|
|
return DCOSException('URL [{0}] is unreachable: {1}'
|
|
.format(url, response))
|
|
elif isinstance(response, requests.exceptions.Timeout):
|
|
return DCOSException('Request to URL [{0}] timed out'.format(url))
|
|
elif isinstance(response, requests.exceptions.RequestException):
|
|
return response
|
|
else:
|
|
return DCOSException(
|
|
'Error while fetching [{0}]: HTTP {1}: {2}'.format(
|
|
url, response.status_code, response.reason))
|
|
|
|
|
|
@util.duration
|
|
def request(method,
|
|
url,
|
|
timeout=3.0,
|
|
is_success=_default_is_success,
|
|
to_exception=_default_to_exception,
|
|
**kwargs):
|
|
"""Sends an HTTP request.
|
|
|
|
:param method: method for the new Request object
|
|
:type method: str
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param is_success: Defines successful status codes for the request
|
|
:type is_success: Function from int to bool
|
|
:param to_exception: Builds an Error from an unsuccessful response or Error
|
|
:type to_exception: (requests.Response | Error) -> Error
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see http://docs.python-requests.org/en/latest/api/#requests.request)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
try:
|
|
if 'headers' in kwargs:
|
|
request = requests.Request(method=method, url=url, **kwargs)
|
|
else:
|
|
request = requests.Request(
|
|
method=method,
|
|
url=url,
|
|
headers={'Accept': 'application/json'},
|
|
**kwargs)
|
|
|
|
logger.info(
|
|
'Sending HTTP [%r] to [%r]: %r',
|
|
request.method,
|
|
request.url,
|
|
request.headers)
|
|
|
|
with requests.Session() as session:
|
|
response = session.send(request.prepare(), timeout=timeout,
|
|
proxies=util.get_proxy_dict_from_env())
|
|
except Exception as ex:
|
|
raise to_exception(ex)
|
|
|
|
logger.info('Received HTTP response [%r]: %r',
|
|
response.status_code,
|
|
response.text)
|
|
|
|
if is_success(response.status_code):
|
|
return response
|
|
else:
|
|
raise to_exception(response)
|
|
|
|
|
|
def head(url, to_exception=_default_to_exception, **kwargs):
|
|
"""Sends a HEAD request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('head', url, **kwargs)
|
|
|
|
|
|
def get(url, to_exception=_default_to_exception, **kwargs):
|
|
"""Sends a GET request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('get', url, to_exception=to_exception, **kwargs)
|
|
|
|
|
|
def post(url, to_exception=_default_to_exception,
|
|
data=None, json=None, **kwargs):
|
|
"""Sends a POST request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param data: Request body
|
|
:type data: dict, bytes, or file-like object
|
|
:param json: JSON request body
|
|
:type data: dict
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('post', url,
|
|
to_exception=to_exception, data=data, json=json, **kwargs)
|
|
|
|
|
|
def put(url, to_exception=_default_to_exception, data=None, **kwargs):
|
|
"""Sends a PUT request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param data: Request body
|
|
:type data: dict, bytes, or file-like object
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('put', url, to_exception=to_exception, data=data, **kwargs)
|
|
|
|
|
|
def patch(url, to_exception=_default_to_exception, data=None, **kwargs):
|
|
"""Sends a PATCH request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param data: Request body
|
|
:type data: dict, bytes, or file-like object
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('patch', url,
|
|
to_exception=to_exception, data=data, **kwargs)
|
|
|
|
|
|
def delete(url, to_exception=_default_to_exception, **kwargs):
|
|
"""Sends a DELETE request.
|
|
|
|
:param url: URL for the new Request object
|
|
:type url: str
|
|
:param kwargs: Additional arguments to requests.request
|
|
(see py:func:`request`)
|
|
:type kwargs: dict
|
|
:rtype: Response
|
|
"""
|
|
|
|
return request('delete', url, to_exception=to_exception, **kwargs)
|
|
|
|
|
|
def silence_requests_warnings():
|
|
"""Silence warnings from requests.packages.urllib3. See DCOS-1007."""
|
|
requests.packages.urllib3.disable_warnings()
|