diff --git a/aioupnp/serialization/soap.py b/aioupnp/serialization/soap.py index 9ebc07a..9ee2c08 100644 --- a/aioupnp/serialization/soap.py +++ b/aioupnp/serialization/soap.py @@ -1,5 +1,6 @@ import re import typing +import json from aioupnp.util import flatten_keys from aioupnp.fault import UPnPError from aioupnp.constants import XML_VERSION, ENVELOPE, BODY, FAULT, CONTROL @@ -54,7 +55,10 @@ def deserialize_soap_post_response(response: bytes, method: str, fault: typing.Dict[str, typing.Dict[str, typing.Dict[str, str]]] = flatten_keys( response_body[FAULT], "{%s}" % CONTROL ) - raise UPnPError(fault['detail']['UPnPError']['errorDescription']) + try: + raise UPnPError(fault['detail']['UPnPError']['errorDescription']) + except (KeyError, TypeError, ValueError): + raise UPnPError(f"Failed to decode error response: {json.dumps(fault)}") response_key = None for key in response_body: if method in key: diff --git a/tests/serialization/test_soap.py b/tests/serialization/test_soap.py index ea3cf04..0105498 100644 --- a/tests/serialization/test_soap.py +++ b/tests/serialization/test_soap.py @@ -58,6 +58,16 @@ class TestSOAPSerialization(unittest.TestCase): b"\r\n" \ b"\n\n\t\n\t\t\n\t\t\ts:Client\n\t\t\tUPnPError\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t713\n\t\t\t\t\tSpecifiedArrayIndexInvalid\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n\n" + error_response_no_description = b"HTTP/1.1 500 Internal Server Error\r\n" \ + b"Server: WebServer\r\n" \ + b"Date: Thu, 11 Oct 2018 22:16:17 GMT\r\n" \ + b"Connection: close\r\n" \ + b"CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n" \ + b"CONTENT-LENGTH: 429 \r\n" \ + b"EXT:\r\n" \ + b"\r\n" \ + b"\n\n\t\n\t\t\n\t\t\ts:Client\n\t\t\tUPnPError\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t713\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n\n" + def test_serialize_post(self): self.assertEqual(serialize_soap_post( self.method, self.param_names, self.st, self.gateway_address, self.path, **self.kwargs @@ -94,3 +104,13 @@ class TestSOAPSerialization(unittest.TestCase): raised = True self.assertTrue(str(err) == 'SpecifiedArrayIndexInvalid') self.assertTrue(raised) + + def test_raise_from_error_response_without_error_description(self): + raised = False + expected = 'Failed to decode error response: {"faultcode": "s:Client", "faultstring": "UPnPError", "detail": {"UPnPError": {"errorCode": "713"}}}' + try: + deserialize_soap_post_response(self.error_response_no_description, self.method, service_id=self.st.decode()) + except UPnPError as err: + raised = True + self.assertTrue(str(err) == expected) + self.assertTrue(raised)