diff --git a/CHANGES b/CHANGES index b700804..27650b5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +1.27.7 +------- +- Include the server's error message in the HTTPError raised by raise_for_status for all error statuses + 1.27.6 ------- - Only parse the response body and decode the reason in raise_for_status when an error is actually raised diff --git a/intezer_sdk/__init__.py b/intezer_sdk/__init__.py index 51de7bd..9b39547 100644 --- a/intezer_sdk/__init__.py +++ b/intezer_sdk/__init__.py @@ -1 +1 @@ -__version__ = '1.27.6' +__version__ = '1.27.7' diff --git a/intezer_sdk/api.py b/intezer_sdk/api.py index 90b5b11..df3a827 100644 --- a/intezer_sdk/api.py +++ b/intezer_sdk/api.py @@ -35,6 +35,7 @@ def raise_for_status(response: requests.Response, """Raises stored :class:`HTTPError`, if one occurred.""" should_raise = False http_error_msg = '' + response_json = {} if statuses_to_ignore and response.status_code in statuses_to_ignore: return elif allowed_statuses and response.status_code not in allowed_statuses: @@ -43,7 +44,7 @@ def raise_for_status(response: requests.Response, try: response_json = response.json() except Exception: - response_json = {} + pass should_raise = True if response.status_code == HTTPStatus.UNAUTHORIZED: raise errors.InvalidApiKeyError(response) @@ -65,6 +66,9 @@ def raise_for_status(response: requests.Response, else: reason = response.reason http_error_msg = f'{response.status_code} Client Error: {reason} for url: {response.url}' + server_error = response_json.get('error') + if server_error: + http_error_msg = f'{http_error_msg}, server returns {server_error}' else: http_error_msg = f'{http_error_msg}, server returns {response_json.get("error")}, details: {response_json.get("details")}' raise requests.HTTPError(http_error_msg, response=response) diff --git a/tests/unit/base_test.py b/tests/unit/base_test.py index 93185e4..4f34c34 100644 --- a/tests/unit/base_test.py +++ b/tests/unit/base_test.py @@ -5,6 +5,7 @@ from http import HTTPStatus from unittest.mock import MagicMock +import requests import responses from intezer_sdk import consts @@ -84,6 +85,29 @@ def test_api_raise_insufficient_permissions_error_when_insufficient_permissions_ with self.assertRaises(errors.InsufficientPermissionsError): raise_for_status(response) + def test_api_raises_http_error_with_server_error_message_when_conflict_received(self): + # Arrange + with responses.RequestsMock() as mock: + mock.add('POST', + url=f'{self.full_url}/get-access-token', + status=HTTPStatus.OK, + json={'result': 'access-token', 'expire_at': 2166920067}) + api = set_global_api() + api.authenticate() + + with responses.RequestsMock() as mock: + mock.add('POST', + f'{self.full_url}/some-route', + status=HTTPStatus.CONFLICT, + json={'error': 'Windows scanner version 1.0.1.20 is not supported'}) + response = api.request_with_refresh_expired_access_token(method='POST', path='/some-route') + + # Act & Assert + with self.assertRaises(requests.HTTPError) as context: + raise_for_status(response) + + self.assertIn('Windows scanner version 1.0.1.20 is not supported', str(context.exception)) + def test_api_raise_invalid_api_key_error_when_unauthorized_received(self): # Arrange with responses.RequestsMock() as mock: