Python SOAP client calling WSDL with foam gives transport error 401 Unauthorized for basic HTTP authentication

Background

I am creating a SOAP client with python 2.7.3 and using the suds 0.4.1 library provided by Canonical. The server uses basic authentication over HTTPS.

Problem

Unable to authenticate to the server, even to gain access to the WSDL. I get the following error:

suds.transport.TransportError: HTTP Error 401: Unauthorized

Attempts to resolve and code

I tried both authentication methods described in suds documentation , but I still get the error above in the line client = Client(url, ...) . I confirmed the credentials and connectivity in a web browser that works fine.

After declaring wsdl_url , username and password I tried:

 client = Client(url=wsdl_url, username=username, password=password) # as well as: t = HttpAuthenticated(username=username, password=password) client = Client(url=wsdl_url, transport=t) # and even: t = HttpAuthenticated(username=username, password=password) t.handler = urllib2.HTTPBasicAuthHandler(t.pm) t.urlopener = urllib2.build_opener(t.handler) client = Client(url=wsdl_url, transport=t) 

The latter, at least, seems to receive a response from the WSDL URL in another question about HTTP authentication using suds .

Other notes

This question is different from this similar question because I use:

 from suds.transport.https import HttpAuthenticated # not: # from suds.transport.http import HttpAuthenticated 

and from Traceback, calling client = Client(url, ...) explicitly shows suds.transport.https.py:

 File "/usr/lib/python2.7/dist-packages/suds/client.py", line 112, in __init__ self.wsdl = reader.open(url) File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 152, in open d = self.fn(url, self.options) File "/usr/lib/python2.7/dist-packages/suds/wsdl.py", line 136, in __init__ d = reader.open(url) File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 79, in open d = self.download(url) File "/usr/lib/python2.7/dist-packages/suds/reader.py", line 95, in download fp = self.options.transport.open(Request(url)) File "/usr/lib/python2.7/dist-packages/suds/transport/https.py", line 60, in open return HttpTransport.open(self, request) File "/usr/lib/python2.7/dist-packages/suds/transport/http.py", line 64, in open raise TransportError(str(e), e.code, e.fp) 

What am I missing?

+8
python soap wsdl basic-authentication suds
source share
2 answers

suds did not add an authorization header to the request, so I set it manually:

 import base64 # code excluded for brevity base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') authenticationHeader = { "SOAPAction" : "ActionName", "Authorization" : "Basic %s" % base64string } client = Client(url=wsdl_url, headers=authenticationHeader) 
+11
source

You can use SOAPpy

 import SOAPpy, base64 class myHTTPTransport(SOAPpy.HTTPTransport): username = None passwd = None @classmethod def setAuthentication(cls,u,p): cls.username = u cls.passwd = p def call(self, addr, data, namespace, soapaction=None, encoding=None, http_proxy=None, config=SOAPpy.Config, timeout=None): if not isinstance(addr, SOAPpy.SOAPAddress): addr = SOAPpy.SOAPAddress(addr, config) if self.username != None: addr.user = self.username+":"+self.passwd return SOAPpy.HTTPTransport.call(self, addr, data, namespace, soapaction, encoding, http_proxy, config) if __name__ == '__main__': # code for authenticating the SOAP API calls myHTTPTransport.setAuthentication('admin', 'admin') # Getting the instance of Server Baton = SOAPpy.WSDL.Proxy(<WSDL PATH>, transport=myHTTPTransport) # your code goes here ... 
0
source

All Articles