mvantellingen / python-zeep

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

Plugins fundamentally broken (egress missing 'binding_options') #1294

Closed XMol closed 2 years ago

XMol commented 2 years ago
  1. The version of zeep (or if you are running master the commit hash/date) - 4.1.0
  2. The WSDL you are using - http://www.soapclient.com/xml/soapresponder.wsdl
  3. runnable example script
    
    from zeep import Client, Plugin

class MyPlugin (Plugin): pass

client = Client('http://www.soapclient.com/xml/soapresponder.wsdl', plugins=[MyPlugin])

client.service.Method1('Hello', 'zeep') Traceback (most recent call last): File "", line 1, in File "/opt/rh/rh-python38/root/usr/local/lib/python3.8/site-packages/zeep/proxy.py", line 46, in call return self._proxy._binding.send( File "/opt/rh/rh-python38/root/usr/local/lib/python3.8/site-packages/zeep/wsdl/bindings/soap.py", line 123, in send envelope, http_headers = self._create( File "/opt/rh/rh-python38/root/usr/local/lib/python3.8/site-packages/zeep/wsdl/bindings/soap.py", line 90, in _create envelope, http_headers = plugins.apply_egress( File "/opt/rh/rh-python38/root/usr/local/lib/python3.8/site-packages/zeep/plugins.py", line 33, in apply_egress result = plugin.egress(envelope, http_headers, operation, binding_options) TypeError: egress() missing 1 required positional argument: 'binding_options'



This demonstrates that any plugin (including the HistoryPlugin) triggers an exception upon rendering a message.
XMol commented 2 years ago

The problem is, that there is no actually instantiated object of the plugins, but the egress() and ingress() functions are called from the Plugin class definition. Thus self as first function argument is wrong.

This problem can be mitigated by defining egress() and ingress() in custom plugins without self.

from zeep import Client, Plugin

class MyPlugin (Plugin):
    def egress(envelope, http_headers, operation, binding_options):
        return None
    def ingress(envelope, http_headers, operation):
        return None

client = Client('http://www.soapclient.com/xml/soapresponder.wsdl', plugins=[MyPlugin])

client.service.Method1('Hello', 'zeep')
# => 'Your input parameters are Hello and zeep'
XMol commented 2 years ago

Now that I've understood the issue for myself and had time to think about it more, I see my mistake in all this:

from zeep import Client, Plugin

class MyPlugin (Plugin):
    pass

client = Client('http://www.soapclient.com/xml/soapresponder.wsdl', plugins=[MyPlugin()])
client.service.Method1('Hello', 'zeep') # => 'Your input parameters are Hello and zeep'

The problem is, that there is no actually instantiated object of the plugins [...]

The solution then is much simpler: Feed an instance of the plugin into the Client. 🤦‍♂️