def test_clienterror_exception(self): args = [ "GET", "http://localhost:8080", HTTPError("oh no") ] kwargs = { "method": "GET", "url": "http://localhost:8080", "exception": HTTPError("oh no") } with pytest.raises(ClientError): raise ClientError(*args) with pytest.raises(DatadogException): raise ClientError(*args) with pytest.raises(ClientError): raise ClientError(**kwargs) with pytest.raises(DatadogException): raise ClientError(**kwargs)
def request(cls, method, url, headers, params, data, timeout, proxies, verify, max_retries): """ Wrapper around `urlfetch.fetch` method. TO IMPLEMENT: * `max_retries` """ # No local certificate file can be used on Google App Engine validate_certificate = True if verify else False # Encode parameters in the url url_with_params = "{url}?{params}".format( url=url, params=urllib.urlencode(params)) try: result = urlfetch.fetch(url=url_with_params, method=method, headers=headers, validate_certificate=validate_certificate, deadline=timeout, payload=data) cls.raise_on_status(result) except urlfetch.DownloadError as e: raise ClientError(method, url, e) except urlfetch_errors.DeadlineExceededError: raise HttpTimeout(method, url, timeout) return result
def request(cls, method, url, headers, params, data, timeout, proxies, verify, max_retries): """ Wrapper around `urlfetch.fetch` method. TO IMPLEMENT: * `max_retries` """ # No local certificate file can be used on Google App Engine validate_certificate = True if verify else False # Encode parameters in the url url_with_params = "{url}?{params}".format( url=url, params=urllib.urlencode(params)) try: result = urlfetch.fetch( url=url_with_params, method=method, headers=headers, validate_certificate=validate_certificate, deadline=timeout, payload=data, # setting follow_redirects=False may be slightly faster: # https://cloud.google.com/appengine/docs/python/microservice-performance#use_the_shortest_route follow_redirects=False) cls.raise_on_status(result) except urlfetch.DownloadError as e: raise ClientError(method, url, e) except urlfetch_errors.DeadlineExceededError: raise HttpTimeout(method, url, timeout) return result
def request(cls, method, url, headers, params, data, timeout, proxies, verify, max_retries): try: with cls._session_lock: if cls._session is None: cls._session = requests.Session() http_adapter = requests.adapters.HTTPAdapter(max_retries=max_retries) cls._session.mount('https://', http_adapter) result = cls._session.request( method, url, headers=headers, params=params, data=data, timeout=timeout, proxies=proxies, verify=verify) result.raise_for_status() except requests.ConnectionError as e: raise _remove_context(ClientError(method, url, e)) except requests.exceptions.Timeout: raise _remove_context(HttpTimeout(method, url, timeout)) except requests.exceptions.HTTPError as e: if e.response.status_code in (400, 401, 403, 404, 409, 429): # This gets caught afterwards and raises an ApiError exception pass else: raise _remove_context(HTTPError(e.response.status_code, result.reason)) except TypeError as e: raise TypeError( u"Your installed version of `requests` library seems not compatible with" u"Datadog's usage. We recommand upgrading it ('pip install -U requests')." u"If you need help or have any question, please contact [email protected]" ) return result
def request(cls, method, path, body=None, attach_host_name=False, response_formatter=None, error_formatter=None, **params): """ Make an HTTP API request :param method: HTTP method to use to contact API endpoint :type method: HTTP method string :param path: API endpoint url :type path: url :param body: dictionnary to be sent in the body of the request :type body: dictionary :param response_formatter: function to format JSON response from HTTP API request :type response_formatter: JSON input function :param error_formatter: function to format JSON error response from HTTP API request :type error_formatter: JSON input function :param attach_host_name: link the new resource object to the host name :type attach_host_name: bool :param params: dictionnary to be sent in the query string of the request :type params: dictionary :returns: JSON or formated response from HTTP API request """ try: # Check if it's ok to submit if not cls._should_submit(): raise HttpBackoff( "Too many timeouts. Won't try again for {1} seconds.". format(*cls._backoff_status())) # Import API, User and HTTP settings from datadog.api import _api_key, _application_key, _api_host, \ _swallow, _host_name, _proxies, _max_retries, _timeout # Check keys and add then to params if _api_key is None: raise ApiNotInitialized( "API key is not set." " Please run 'initialize' method first.") params['api_key'] = _api_key if _application_key: params['application_key'] = _application_key # Construct the url url = "%s/api/%s/%s" % (_api_host, cls._api_version, path.lstrip("/")) # Attach host name to body if attach_host_name and body: # Is it a 'series' list of objects ? if 'series' in body: # Adding the host name to all objects for obj_params in body['series']: if 'host' not in obj_params: obj_params['host'] = _host_name else: if 'host' not in body: body['host'] = _host_name # If defined, make sure tags are defined as a comma-separated string if 'tags' in params and isinstance(params['tags'], list): params['tags'] = ','.join(params['tags']) # Process the body, if necessary headers = {} if isinstance(body, dict): body = json.dumps(body) headers['Content-Type'] = 'application/json' # Process requesting start_time = time.time() try: # Use a session to set a max_retries parameters s = requests.Session() http_adapter = requests.adapters.HTTPAdapter( max_retries=_max_retries) s.mount('https://', http_adapter) # Request result = s.request(method, url, headers=headers, params=params, data=body, timeout=_timeout, proxies=_proxies) result.raise_for_status() except requests.ConnectionError as e: raise ClientError("Could not request %s %s%s: %s" % (method, _api_host, url, e)) except requests.exceptions.Timeout as e: cls._timeout_counter += 1 raise HttpTimeout('%s %s timed out after %d seconds.' % (method, url, _timeout)) except requests.exceptions.HTTPError as e: if e.response.status_code == 404 or e.response.status_code == 400: pass else: raise except TypeError as e: raise TypeError( "Your installed version of 'requests' library seems not compatible with" "Datadog's usage. We recommand upgrading it ('pip install -U requests')." "If you need help or have any question, please contact [email protected]" ) # Request succeeded: log it and reset the timeout counter duration = round((time.time() - start_time) * 1000., 4) log.info("%s %s %s (%sms)" % (result.status_code, method, url, duration)) cls._timeout_counter = 0 # Format response content content = result.content if content: try: if is_p3k(): response_obj = json.loads(content.decode('utf-8')) else: response_obj = json.loads(content) except ValueError: raise ValueError( 'Invalid JSON response: {0}'.format(content)) if response_obj and 'errors' in response_obj: raise ApiError(response_obj) else: response_obj = None if response_formatter is None: return response_obj else: return response_formatter(response_obj) except ClientError as e: if _swallow: log.error(str(e)) if error_formatter is None: return {'errors': e.args[0]} else: return error_formatter({'errors': e.args[0]}) else: raise except ApiError as e: if _swallow: for error in e.args[0]['errors']: log.error(str(error)) if error_formatter is None: return e.args[0] else: return error_formatter(e.args[0]) else: raise