From a2e5671921b374fe93268f07edead0d2b6e5d9e6 Mon Sep 17 00:00:00 2001
From: Florian Spreckelsen <f.spreckelsen@indiscale.com>
Date: Thu, 12 Dec 2024 11:25:55 +0100
Subject: [PATCH 1/4] TST: Add test for
 https://gitlab.com/linkahead/linkahead-pylib/-/issues/87

---
 unittests/test_error_handling.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/unittests/test_error_handling.py b/unittests/test_error_handling.py
index 3f524146..c7325341 100644
--- a/unittests/test_error_handling.py
+++ b/unittests/test_error_handling.py
@@ -30,7 +30,7 @@ import linkahead as db
 from linkahead.common.models import raise_errors
 from linkahead.exceptions import (AuthorizationError,
                                   EntityDoesNotExistError, EntityError,
-                                  EntityHasNoDatatypeError,
+                                  EntityHasNoDatatypeError, HTTPServerError,
                                   TransactionError, UniqueNamesError,
                                   UnqualifiedParentsError,
                                   UnqualifiedPropertiesError)
@@ -315,3 +315,9 @@ def test_container_with_faulty_elements():
             # record raises both of them
             assert (isinstance(err, UnqualifiedParentsError) or
                     isinstance(err, UnqualifiedPropertiesError))
+
+
+def test_incomplete_server_error_response():
+    """The reason behind https://gitlab.com/linkahead/linkahead-pylib/-/issues/87."""
+    err = HTTPServerError("Bla")
+    assert str(err) == "Bla"
-- 
GitLab


From 4d6d1c8619d3e72dc3b87e1e05b4b318d849526b Mon Sep 17 00:00:00 2001
From: Florian Spreckelsen <f.spreckelsen@indiscale.com>
Date: Thu, 12 Dec 2024 11:40:58 +0100
Subject: [PATCH 2/4] TST: extend tests for
 https://gitlab.com/linkahead/linkahead-pylib/-/issues/87

---
 unittests/test_error_handling.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/unittests/test_error_handling.py b/unittests/test_error_handling.py
index c7325341..64f743c8 100644
--- a/unittests/test_error_handling.py
+++ b/unittests/test_error_handling.py
@@ -319,5 +319,22 @@ def test_container_with_faulty_elements():
 
 def test_incomplete_server_error_response():
     """The reason behind https://gitlab.com/linkahead/linkahead-pylib/-/issues/87."""
+    # Case 1: Response is no XML at all
     err = HTTPServerError("Bla")
     assert str(err) == "Bla"
+
+    # Case 2: Response is an incomplete XML, e.g. due to very unlucky timeout
+    err = HTTPServerError("<incomplete>XML</inc")
+    assert str(err) == "<incomplete>XML</inc"
+
+    # Case 3: Response is complete XML but doesn't have response and or error information
+    err = HTTPServerError("<complete>XML</complete>")
+    assert str(err) == "<complete>XML</complete>"
+
+    # Case 4: Response is an XML response but the error is lacking a description
+    err = HTTPServerError("<Response><Error>complete error</Error></Response>")
+    assert str(err) == "complete error"
+
+    # Case 5: Healthy error Response
+    err = HTTPServerError("<Response><Error description='Error'>complete error</Error></Response>")
+    assert str(err) == "Error\n\ncomplete error"
-- 
GitLab


From 8883815a4a7a16c8ef1ed333bcee1fa8f79629fa Mon Sep 17 00:00:00 2001
From: Florian Spreckelsen <f.spreckelsen@indiscale.com>
Date: Thu, 12 Dec 2024 11:41:19 +0100
Subject: [PATCH 3/4] BUG: Fix
 https://gitlab.com/linkahead/linkahead-pylib/-/issues/87

---
 src/linkahead/exceptions.py | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/linkahead/exceptions.py b/src/linkahead/exceptions.py
index 609d3654..7d4dc085 100644
--- a/src/linkahead/exceptions.py
+++ b/src/linkahead/exceptions.py
@@ -94,12 +94,26 @@ class HTTPServerError(LinkAheadException):
     """HTTPServerError represents 5xx HTTP server errors."""
 
     def __init__(self, body):
-        xml = etree.fromstring(body)
-        error = xml.xpath('/Response/Error')[0]
-        msg = error.get("description")
-
-        if error.text is not None:
-            msg = msg + "\n\n" + error.text
+        try:
+            # This only works if the server sends a valid XML
+            # response. Then it can be parsed for more information.
+            xml = etree.fromstring(body)
+            if xml.xpath('/Response/Error'):
+                error = xml.xpath('/Response/Error')[0]
+                msg = error.get("description") if error.get("description") is not None else ""
+
+                if error.text is not None:
+                    if msg:
+                        msg = msg + "\n\n" + error.text
+                    else:
+                        msg = error.text
+            else:
+                # Valid XML, but no error information
+                msg = body
+        except etree.XMLSyntaxError:
+            # Handling of incomplete responses, e.g., due to timeouts,
+            # c.f. https://gitlab.com/linkahead/linkahead-pylib/-/issues/87.
+            msg = body
         LinkAheadException.__init__(self, msg)
 
 
-- 
GitLab


From 84443119172283b71f60a3516784a2595a06e69a Mon Sep 17 00:00:00 2001
From: Florian Spreckelsen <f.spreckelsen@indiscale.com>
Date: Thu, 12 Dec 2024 12:02:38 +0100
Subject: [PATCH 4/4] DOC: Update Changelog

---
 CHANGELOG.md | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 928c5230..e1fd615a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,7 +27,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   `authentication/interface/on_response()` does not overwrite
   `auth_token` if new value is `None`
 * [#119](https://gitlab.com/linkahead/linkahead-pylib/-/issues/119)
-  The diff returned by compare_entities now uses id instead of name as key if either property does not have a name
+  The diff returned by compare_entities now uses id instead of name as
+  key if either property does not have a name
+* [#87](https://gitlab.com/linkahead/linkahead-pylib/-/issues/87)
+  `XMLSyntaxError` messages when parsing (incomplete) responses in
+  case of certain connection timeouts.
 
 ### Security ###
 
-- 
GitLab