From 0c820a73247e2ec26559af062b7fb7f65cc0c41f Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Wed, 23 Apr 2025 11:44:59 +0300 Subject: [PATCH 1/2] fix(api): improve error handling for invalid JSON responses - enhance `_get_error_message` to handle JSON decode errors - add detailed error message including the invalid response text - add tests covering valid JSON, invalid JSON, and non-JSON responses --- src/typesense/request_handler.py | 7 +++++-- tests/api_call_test.py | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/typesense/request_handler.py b/src/typesense/request_handler.py index b9f822a..18ece90 100644 --- a/src/typesense/request_handler.py +++ b/src/typesense/request_handler.py @@ -260,8 +260,11 @@ def _get_error_message(response: requests.Response) -> str: """ content_type = response.headers.get("Content-Type", "") if content_type.startswith("application/json"): - err_message: str = response.json().get("message", "API error.") - return err_message + try: + err_message: str = response.json().get("message", "API error.") + return err_message + except requests.exceptions.JSONDecodeError: + return f"API error: Invalid JSON response: {response.text}" return "API error." @staticmethod diff --git a/tests/api_call_test.py b/tests/api_call_test.py index caaa4a1..1d5fa11 100644 --- a/tests/api_call_test.py +++ b/tests/api_call_test.py @@ -94,6 +94,41 @@ def test_get_exception() -> None: assert RequestHandler._get_exception(999) == exceptions.TypesenseClientError +def test_get_error_message_with_invalid_json() -> None: + """Test that it correctly handles invalid JSON in error responses.""" + response = requests.Response() + response.headers["Content-Type"] = "application/json" + response.status_code = 400 + # Set an invalid JSON string that would cause JSONDecodeError + response._content = b'{"message": "Error occurred", "details": {"key": "value"' + + error_message = RequestHandler._get_error_message(response) + assert "API error: Invalid JSON response:" in error_message + assert '{"message": "Error occurred", "details": {"key": "value"' in error_message + + +def test_get_error_message_with_valid_json() -> None: + """Test that it correctly extracts error message from valid JSON responses.""" + response = requests.Response() + response.headers["Content-Type"] = "application/json" + response.status_code = 400 + response._content = b'{"message": "Error occurred", "details": {"key": "value"}}' + + error_message = RequestHandler._get_error_message(response) + assert error_message == "Error occurred" + + +def test_get_error_message_with_non_json_content_type() -> None: + """Test that it returns a default error message for non-JSON content types.""" + response = requests.Response() + response.headers["Content-Type"] = "text/plain" + response.status_code = 400 + response._content = b'Not a JSON content' + + error_message = RequestHandler._get_error_message(response) + assert error_message == "API error." + + def test_normalize_params_with_booleans() -> None: """Test that it correctly normalizes boolean values to strings.""" parameter_dict: typing.Dict[str, str | bool] = {"key1": True, "key2": False} From 5b32db0d2ff24b4e21c49c99ed8568f7367a4ad1 Mon Sep 17 00:00:00 2001 From: Fanis Tharropoulos Date: Wed, 23 Apr 2025 11:50:29 +0300 Subject: [PATCH 2/2] refactor(api): fix linting issue with try block --- src/typesense/request_handler.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/typesense/request_handler.py b/src/typesense/request_handler.py index 18ece90..e726379 100644 --- a/src/typesense/request_handler.py +++ b/src/typesense/request_handler.py @@ -261,8 +261,7 @@ def _get_error_message(response: requests.Response) -> str: content_type = response.headers.get("Content-Type", "") if content_type.startswith("application/json"): try: - err_message: str = response.json().get("message", "API error.") - return err_message + return typing.cast(str, response.json().get("message", "API error.")) except requests.exceptions.JSONDecodeError: return f"API error: Invalid JSON response: {response.text}" return "API error."