Pyhass / Pyhiveapi

A python library to interface with the hive home api
MIT License
24 stars 18 forks source link

[BUG] Exception when updating all entities #52

Open von-Chaps opened 2 years ago

von-Chaps commented 2 years ago

getAll() in hive_async_api.py calls self.request("get", url) and then immediately accesses resp.status without checking if resp exists.

There are paths out of the request() method that do not return a valid resp. Indeed line 80 is the only place where a valid resp is returned. All other code paths result in None being returned which causes an exception in getAll().

At the very least, I would expect getAll() to check that a valid resp has been returned before attempting to access the resp.status.

A more thorough fix is probably to ensure that request() actually returns what it says it will in all cases.

This is resulting in stack trackbacks in Home Assistant logs but would also, of course, affect anyone else using this API.

von-Chaps commented 2 years ago

FYI, the actual HTTP status codes that are causing this in my case are: 400, 500, 502, 504

However, of course, this is not particularly interesting. The cause is really that anything that doesn't contain "20" on line 79 causes this.

Incidentally, my guess is that line 79

if operator.contains(str(resp.status), "20"):

should probably be;

if str(resp.status).startswith("20"):

YMMV

von-Chaps commented 2 years ago

Since there doesn't seem to be any interest in this, here is a diff that mitigates the issue.

bash-5.1# diff hive_async_api.py.orig hive_async_api.py
--- hive_async_api.py.orig
+++ hive_async_api.py
@@ -10,7 +10,7 @@
 from pyquery import PyQuery

 from ..helper.const import HTTP_UNAUTHORIZED
-from ..helper.hive_exceptions import FileInUse, NoApiToken
+from ..helper.hive_exceptions import FileInUse, NoApiToken, HiveApiError

 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

@@ -89,6 +89,8 @@
                 f"Something has gone wrong calling {url} - "
                 f"HTTP status is - {resp.status}"
             )
+
+        raise HiveApiError

     def getLoginInfo(self):
         """Get login properties to make the login request."""