mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.88k stars 586 forks source link

Handle non-standard responses #126

Closed mattpepin closed 8 years ago

mattpepin commented 8 years ago

Here's the reply from a cheap ONVIF camera to a request. Note the capitalized SOAP-ENV.

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:wsc="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:tdn="http://www.onvif.org/ver10/network/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl"><SOAP-ENV:Header><wsse:Security SOAP-ENV:mustUnderstand="true"><wsse:UsernameToken><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">ciLbvL93z2JoRqiooisuLXknuMw=</wsse:Password><wsse:Nonce>bxsi9NqLob59qLArRajhYw==</wsse:Nonce><wsu:Created>2016-07-14T19:07:51+00:00</wsu:Created></wsse:UsernameToken></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body><tds:GetDeviceInformationResponse><tds:Manufacturer>FOSCAM</tds:Manufacturer><tds:Model>FI9821P</tds:Model><tds:FirmwareVersion>2.11.1.119</tds:FirmwareVersion><tds:SerialNumber>00</tds:SerialNumber><tds:HardwareId>1.4.1.10</tds:HardwareId></tds:GetDeviceInformationResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

It makes python-zeep crash since 'soap-env:Body' is not found. Zeep works fine for better cameras with proper soap-env:Body. There should be a way to handle stupid devices like this one...

mvantellingen commented 8 years ago

The capitalized SOAP-ENV shouldn't be a problem. It it just a shorthand for the long namespace (via xmlns:=).

Do you have a traceback for me?

mattpepin commented 8 years ago

Sure!

Traceback (most recent call last):
  File "onvif-test.py", line 54, in <module>
    print(o.devicemgmt.GetDeviceInformation())
  File "test/lib/python3.5/site-packages/zeep/client.py", line 24, in __call__
    self._op_name, args, kwargs)
  File "test/lib/python3.5/site-packages/zeep/wsdl/soap.py", line 94, in send
    return self.process_reply(client, operation_obj, response)
  File "test/lib/python3.5/site-packages/zeep/wsdl/soap.py", line 125, in process_reply
    return operation.process_reply(doc)
  File "test/lib/python3.5/site-packages/zeep/wsdl/soap.py", line 249, in process_reply
    return self.output.deserialize(node)
  File "test/lib/python3.5/site-packages/zeep/wsdl/messages.py", line 237, in deserialize
    elm = node.find(part.element.qname)
AttributeError: 'NoneType' object has no attribute 'find'
mvantellingen commented 8 years ago

Can you add the following in SoapOperation.process_reply():

assert node is not None, "No {%s}:Body found" % (self.nsmap['soap-env'])

That is after: node = envelope.find('soap-env:Body', namespaces=self.nsmap)

mattpepin commented 8 years ago

AssertionError: No {http://www.w3.org/2003/05/soap-envelope}:Body found

mattpepin commented 8 years ago

Ah, it looks like the camera is using the wrong namespace: http://schemas.xmlsoap.org/soap/envelope instead of http://www.w3.org/2003/05/soap-envelope Not sure what that implies...

mvantellingen commented 8 years ago

Hm it seems 'http://www.w3.org/2003/05/soap-envelope' is for soap 1.2. Which means it's a bug in zeep :-)

mvantellingen commented 8 years ago

Let me know if it isn't fixed. Thanks for reporting

mattpepin commented 8 years ago

Hum nope! I still get:

AssertionError: No {http://www.w3.org/2003/05/soap-envelope}Body found

mvantellingen commented 8 years ago

Ah okay, so I didn't read your reply correctly. It seems that soap 1.2 is used but the response returns a namespace for soap 1.1. I'll need to check this later

mattpepin commented 8 years ago

Thanks!

mvantellingen commented 8 years ago

Looked at it a bit better now:

The issue is that the request is done via the Soap1.2 binding (and that is the only binding in the wsdl) and the response is a Soap 1.1 response. This seems to be a bug on the server. There is some documentation about handling version mismatches (https://www.w3.org/TR/soap12-part1/#version) but that doesn't seem to apply here.

You can work around this issue by subclassing the transport class and altering the response in the post() method there (a really naive example: content = content.replace(<soap 1.1 namespace>, <soap 1.2 namespace>) .