suds-community / suds

Suds is a lightweight SOAP python client for consuming Web Services. A community fork of the jurko fork.
https://suds.readthedocs.io/
GNU Lesser General Public License v3.0
173 stars 56 forks source link

Add "invoked" to MessagePlugin #88

Open Adrian-at-CrimsonAzure opened 2 years ago

Adrian-at-CrimsonAzure commented 2 years ago

It would be helpful to allow a plugin to alter the args when a method is called before they've been converted to XML within _SoapClient.invoke here before binding.get_message is called. My use case is that I want to be able to inject the credentials for the API I'm using into every message without having to add them to the payload manually every time.

If I'm overthinking things and there's a better way/place to add this functionality, I'd love to hear it.

phillbaker commented 2 years ago

Hi @Adrian-at-CrimsonAuzre, thanks for opening an issue. Can you add a short psuedo code example of what you're doing today and what the proposed plugin interface would look like?

Adrian-at-CrimsonAzure commented 1 year ago

We ended up going with a different vendor that does not use SOAP, so our need for this feature has vanished. This is roughly what I had in mind though:

    def invoke(self, args, kwargs):
        timer = metrics.Timer()
        timer.start()
        binding = self.method.binding.input
        timeout = kwargs.pop(_SoapClient.TIMEOUT_ARGUMENT, None)

        plugins = PluginContainer(self.options.plugins)
        plugins.message.invoked(args, kwargs)

        soapenv = binding.get_message(self.method, args, kwargs)
        timer.stop()
        method_name = self.method.name
        metrics.log.debug("message for '%s' created: %s", method_name, timer)
        timer.start()
        result = self.send(soapenv, timeout=timeout)
        timer.stop()
        metrics.log.debug("method '%s' invoked: %s", method_name, timer)
        return result

Then when you register a plugin and override invoked, you can modify the object you are passing to the service before it's parsed to XML. In my case, adding a static Credentials object to everything that gets sent so it didn't need to be manually set with every call to the API.