0

I'm trying to do simple SOAP call with WSDL and authentication, but don't know really how to pass credentials to the call. Is this possible with WSDL, or should I do this some other way?

from SOAPpy import WSDL

WSDLFILE = 'link/to/wsdl/file'
server = WSDL.Proxy(WSDLFILE)

result = server.methodCall()

Right now, I'm getting this error:

File "/usr/lib/pymodules/python2.7/SOAPpy/Client.py", line 263, in call
raise HTTPError(code, msg)
SOAPpy.Errors.HTTPError: <HTTPError 401 Unauthorized>
erhesto
  • 1,176
  • 7
  • 20
  • 1
    SOAPpy is deprecated in favor of [suds](https://fedorahosted.org/suds/) - I have used suds with success, check out their examples. – Kyle Pittman Oct 07 '15 at 14:34
  • @Monkey Thanks, there is incredible difference between these two - suds is so much easier. – erhesto Oct 07 '15 at 14:44
  • @Monkpit and @orhesto - suds seems to be abandoned, SOAPpy too though much more `fresh` than suds... – Greg0ry Aug 03 '16 at 20:21
  • @Greg0ry I find that suds does a much better job of actually working :) regardless of age. – Kyle Pittman Aug 03 '16 at 21:42
  • Agree, though it looks like you can make SOAPpy working in this scenario too. Out of interest - I cannot find anything better than suds or SOAPpy, is there any such project that would be still alive? Or are web services dying? – Greg0ry Aug 03 '16 at 23:28

1 Answers1

1

Quite an old question but since it shows up first when googling "SOAPpy authentication" - I will leave my findings so maybe you won't have to bang your head for 10 hours. Giving back to community.

Googling does not provide much help but this sample here (http://code.activestate.com/recipes/444758-how-to-add-cookiesheaders-to-soappy-calls/) made me to write my own helper (version 0.0 beta)

from SOAPpy import (
    WSDL,
    HTTPTransport,
    Config,
    SOAPAddress,
)
import urllib2
import base64

class AuthenticatedTransport(HTTPTransport):
    _username = None
    _password = None

    def call(self, addr, data, namespace, soapaction = None, encoding = None, http_proxy = None, config = Config, timeout = 10):
        if not isinstance(addr, SOAPAddress):
            addr = SOAPAddress(addr, config)

        content_type = 'text/xml'
        if encoding != None:
            content_type += '; charset="%s"' % encoding

        encoded_auth = None
        if ( isinstance(AuthenticatedTransport._username, str) != False ):
            if ( isinstance(AuthenticatedTransport._password, str) == False ):
                AuthenticatedTransport._password = ""
            encoded_auth = base64.b64encode('%s:%s' % (self._username, self._password))

        this_request = None
        if ( encoded_auth is not None ):
            this_request = urllib2.Request(
                url=addr.proto + "://" + addr.host + addr.path,
                data=data,
                headers={
                    "Content-Type":content_type,
                    "SOAPAction":"%s" % soapaction,
                    "Authorization":"Basic %s" % encoded_auth
                }
            )
        else:
            this_request = urllib2.Request(
                url=addr.proto + "://" + addr.host + addr.path,
                data=data,
                headers={
                    "Content-Type":content_type,
                    "SOAPAction":"%s" % soapaction,
                }
            )

        response = urllib2.urlopen(this_request)
        data = response.read()

        # get the new namespace
        if namespace is None:
            new_ns = None
        else:
            new_ns = self.getNS(namespace, data)

        # return response payload
        return data, new_ns

WSDL.Config.strictNamespaces = 0

username = "your_username"
password = "your_password"

WSDLFile = "https://%s:%s@some_host/your_wsdl.php?wsdl" % (username, password)
namespace = "http://futureware.biz/mantisconnect"
proxy = WSDL.Proxy(WSDLFile, namespace=namespace, transport = AuthenticatedTransport(username,password))

print(proxy.mc_get_version()) # This is my WSDL call, your will be different

For whatever reason it is not enough to use AuthenticatedTransport class, the WSDL url itself also has to contain user name and password. Maybe it's because SOAP wrapper called by WSDL here is creating separate HTTP session (remember reading about it on SOAPpy mailing list).

Hope this helps somebody.

Greg0ry
  • 931
  • 8
  • 25