Repository: digitalfabrik/integreat-cms

Issue:
Exceptions in TextLab/HIX API not caught
### Describe the Bug
The textlab API is currently not available and crashes all page edit functionality for affected regions.

```
Apr 05 07:15:25 ERROR   django.request - 500 Internal Server Error: /lkmuenchen/pages/de/24515/edit/
Traceback (most recent call last):
  File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.9/http/client.py", line 1255, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1301, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
    self.send(msg)
  File "/usr/lib/python3.9/http/client.py", line 950, in send
    self.connect()
  File "/usr/lib/python3.9/http/client.py", line 1417, in connect
    super().connect()
  File "/usr/lib/python3.9/http/client.py", line 921, in connect
    self.sock = self._create_connection(
  File "/usr/lib/python3.9/socket.py", line 843, in create_connection
    raise err
  File "/usr/lib/python3.9/socket.py", line 831, in create_connection
    sock.connect(sa)
OSError: [Errno 113] No route to host
```


Discussion:

Resolving patch:
diff --git a/integreat_cms/cms/views/utils/hix.py b/integreat_cms/cms/views/utils/hix.py
--- a/integreat_cms/cms/views/utils/hix.py
+++ b/integreat_cms/cms/views/utils/hix.py
@@ -1,10 +1,11 @@
 """
-This file contains functionality to communicate with the textlab api to get the hix-value
+This file contains functionality to communicate with the Textlab api to get the hix-value
 for a given text.
 """
 import json
 import logging
 from functools import lru_cache
+from urllib.error import URLError
 
 from django.conf import settings
 from django.http import JsonResponse
@@ -30,9 +31,13 @@ def lookup_hix_score(text):
     :return: The score for the given text
     :rtype: float
     """
-    return TextlabClient(
-        settings.TEXTLAB_API_USERNAME, settings.TEXTLAB_API_KEY
-    ).benchmark(text)
+    try:
+        return TextlabClient(
+            settings.TEXTLAB_API_USERNAME, settings.TEXTLAB_API_KEY
+        ).benchmark(text)
+    except (URLError, OSError) as e:
+        logger.warning("HIX benchmark API call failed: %r", e)
+        return None
 
 
 @require_POST
diff --git a/integreat_cms/textlab_api/apps.py b/integreat_cms/textlab_api/apps.py
--- a/integreat_cms/textlab_api/apps.py
+++ b/integreat_cms/textlab_api/apps.py
@@ -35,7 +35,7 @@ def ready(self):
                     logger.info(
                         "Textlab API is available at: %r", settings.TEXTLAB_API_URL
                     )
-                except URLError:
-                    logger.info("Textlab API is unavailable")
+                except (URLError, OSError) as e:
+                    logger.info("Textlab API is unavailable: %r", e)
             else:
                 logger.info("Textlab API is disabled")
diff --git a/integreat_cms/textlab_api/textlab_api_client.py b/integreat_cms/textlab_api/textlab_api_client.py
--- a/integreat_cms/textlab_api/textlab_api_client.py
+++ b/integreat_cms/textlab_api/textlab_api_client.py
@@ -1,7 +1,6 @@
 import json
 import logging
 from html import unescape
-from urllib.error import URLError
 from urllib.request import Request, urlopen
 
 from django.conf import settings
@@ -14,6 +13,8 @@ class TextlabClient:
     """
     Client for the textlab api.
     Supports login and hix-score retrieval.
+
+    A detailed API documentation can be found at https://comlab-ulm.github.io/swagger-V8/
     """
 
     def __init__(self, username, password):
@@ -48,11 +49,7 @@ def benchmark(self, text):
         """
         data = {"text": unescape(text), "locale_name": "de_DE"}
         path = "/benchmark/5"
-        try:
-            response = self.post_request(path, data, self.token)
-        except URLError as e:
-            logger.warning("HIX benchmark API call failed: %r", e)
-            return None
+        response = self.post_request(path, data, self.token)
         return response.get("formulaHix", None)
 
     @staticmethod


Test patch: